I'm relatively new to C, coming from python mainly and I want to be able to create a new variable as a string to use the function strcat() based of an integer. For example, if each time I loop through it and increment an integer, 1, a new variable that is a string/char is now "1", and 2, "2" and so on, so that when using strcat(dest, value), it makes a string for example called: (1st loop) "TEST1.txt", (2nd loop) "TEST2.txt" and so on. If this doesn't really make sense, the best way I can describe this is in python, to achieve the exact same thing, say:
a = 1
while True:
file = open("Test" + str(a) + ".txt", "w")
file.close()
a += 1
if a == 10:
break
I know how to do it with strings, for example if a isn't an integer, from the python code to do the "Test" + str(a) in c, i can do:
char* a = "test";
char* b = "1";
strcat(a, b);
if i print that i would get "test1", but I need it to be an integer first then a string so that i can increment it, thanks
There is no great sense to use strcat in this case. Just write
char file_name[] = "test0.txt";
do
{
++file_name[4];
FILE *fp = fopen( file_name , "w")
//...
fclose( fp )
} while ( file_name[4] != '9' );
Or you can usethe function sprintf as for example
#include <stdio.h>
int main(void)
{
char name[10];
int i = 0;
do
{
sprintf( name, "%s%1d%s", "Test", ++i, ".txt" );
printf( "%s\n", name );
} while ( i != 9 );
return 0;
}
The program output is
Test1.txt
Test2.txt
Test3.txt
Test4.txt
Test5.txt
Test6.txt
Test7.txt
Test8.txt
Test9.txt
In the standard library stdlib.h you can use the function itoa to return a string given a integer. (For reference, you can do the reverse using atoi)
char * itoa ( int value, char * str, int base );
I don't have a C reference to hand on the function, but some links to get you started are either here or here.
Related
Here is my C code:
//int MyFunc(char* res); -> This is the definition of C function
char data[4096];
MyFunc(data);
printf("Data is : %s\n", data);
The data variable is updated by the C function. I used bytearray in Python to pass the variable as argument but the updated array is not reflecting. Any working code sample is much appreciated.
EDIT: I am using Python 3.7.
My Python code:
data = bytearray(b'1234567890')
str_buffer = create_string_buffer(bytes(data), len(data))
print(MyFunc(str_buffer))
print(str_buffer.value) #Output: b''
str_buffer does not contain the values updated by MyFunc().
Calling MyFunc() from C# using the below signature works for me. I am looking for a Python 3.7 equivalent of it.
[DllImport("mydll.dll", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
public static extern int MyFunc(StringBuilder data);
A bytearray isn't the right way to pass a char * to a C function. Use create_string_buffer instead. Also, len(data) is an off-by-one error that results in a null terminator not being present, so either stick a + 1 on that or remove it, as the default length is right. Here's a minimal working example. First, a C function that turns every letter uppercase, and returns the number of letters that were already uppercase:
#include <ctype.h>
int MyFunc(char* res) {
int i = 0;
while(*res) {
if(isupper(*res)) {
++i;
} else {
*res = toupper(*res);
}
++res;
}
return i;
}
I compiled it with gcc -fPIC -shared upstring.c -o upstring.so. Since you're on Windows, you'll have to adapt this.
Now, some Python that calls it:
from ctypes import *
upstring = CDLL("./upstring.so") # Since you're on Windows, you'll have to adapt this too.
data = bytearray(b'abc12DEFGHI')
str_buffer = create_string_buffer(bytes(data)) # Note: using len(data) would be an off-by-one error that would lose the null terminator, so either omit it or use len(data)+1
print(upstring.MyFunc(str_buffer)) # prints 6
print(str_buffer.value) # prints b'ABC12DEFGHI'
i am trying to embed a code python in c++. I have this python code :
#include <Python.h>
int main(int arg)
{
Py_SetProgramName(argv[0]);
Py_Initialize();
PyRun_SimpleString("from time import time,ctime\n"
"print 'Today is',ctime(time())\0");
Py_Finalize();
return 0;
}
but what i want is something like that :
include
int main(int arg)
{
Py_SetProgramName(argv[0]);
int a = 5;
Py_Initialize();
PyRun_SimpleString("a = " + a);
Py_Finalize();
return 0;
}
but it does not work. I mean i want with python to display the value of the variable a.
Thank you :)
You could use std::to_string to convert your int to a string and then use std::string::c_str to get a temporary const char* to the internal data for the duration of the function call:
PyRun_SimpleString(("a = " + std::to_string(a)).c_str());
You have to use correct C syntax in the C code; in C, "a = "+a does not concatenate strings (as you might assume), but calculate a useless pointer that points a bytes behind the start of the constant string "a = ". With a being 5, there is nothing useful at that place.
Concatenating strings is not that straightforward in C; you need to handle preparing memory for the target, etc.; same for converting a number to a string. For example:
char buffer[30];
sprintf(buffer,"a = %d\n",a);
and then
PyRun_SimpleString(buffer);
I'm parsing a GLSL source code and I need to replace global variable name with a new name. The problem is how to take care of shadow variable? For example, in the following source code, I would like to replace lines a = 1 and a = 3 but not a = 2 because of the local declaration.
int a; // To be replaced
void some_function(void)
{
a = 1; // To be replaced
{
int a;
a = 2; // To be kept
}
a = 3; // To be replaced
}
I'm using pyparsing but I did not find a solution (apart using nestedExpr and re-parsing each block).
Refering to http://mail.python.org/pipermail/python-dev/2009-June/090210.html
AND http://dan.iel.fm/posts/python-c-extensions/
and here is other places i searched regarding my question:
http://article.gmane.org/gmane.comp.python.general/424736
http://joyrex.spc.uchicago.edu/bookshelves/python/cookbook/pythoncook-CHP-16-SECT-3.html
http://docs.python.org/2/c-api/sequence.html#PySequence_Check
Python extension module with variable number of arguments
I am inexperienced in Python/C API.
I have the following code:
sm_int_list = (1,20,3)
c_int_array = (ctypes.c_int * len(sm_int_list))(*sm_int_list)
sm_str_tuple = ('some','text', 'here')
On the C extension side, i have done something like this:
static PyObject* stuff_here(PyObject *self, PyObject *args)
{
char* input;
int *i1, *i2;
char *s1, *s2;
// args = (('some','text', 'here'), [1,20,3], ('some','text', 'here'), [1,20,3])
**PyArg_ParseTuple(args, "(s#:):#(i:)#(s#:):#(i:)#", &s1, &i1, &s2, &i2)**;
/*stuff*/
}
such that:
stuff.here(('some','text', 'here'), [1,20,3], ('some','text', 'here'), [1,20,3])
returns data in the same form as args after some computation.
I would like to know the PyArg_ParseTuple expression, is it the proper way to parse
an array of varying string
an array of integers
UPDATE NEW
Is this the correct way?:
static PyObject* stuff_here(PyObject *self, PyObject *args)
unsigned int tint[], cint[];
ttotal=0, ctotal=0;
char *tstr, *cstr;
int *t_counts, *c_counts;
Py_ssize_t size;
PyObject *t_str1, *t_int1, *c_str2, *c_int2; //the C var that takes in the py variable value
PyObject *tseq, cseq;
int t_seqlen=0, c_seqlen=0;
if (!PyArg_ParseTuple(args, "OOiOOi", &t_str1, &t_int1, &ttotal, &c_str2, &c_int2, &ctotal))
{
return NULL;
}
if (!PySequence_Check(tag_str1) && !PySequence_Check(cat_str2)) return NULL;
else:
{
//All things t
tseq = PySequence_Fast(t_str1, "iterable");
t_seqlen = PySequence_Fast_GET_SIZE(tseq);
t_counts = PySequence_Fast(t_int1);
//All things c
cseq = PySequence_Fast(c_str2);
c_seqlen = PySequence_Fast_GET_SIZE(cseq);
c_counts = PySequence_Fast(c_int2);
//Make c arrays of all things tag and cat
for (i=0; i<t_seqlen; i++)
{
tstr[i] = PySequence_Fast_GET_ITEM(tseq, i);
tcounts[i] = PySequence_Fast_GET_ITEM(t_counts, i);
}
for (i=0; i<c_seqlen; i++)
{
cstr[i] = PySequence_Fast_GET_ITEM(cseq, i);
ccounts[i] = PySequence_Fast_GET_ITEM(c_counts, i);
}
}
OR
PyArg_ParseTuple(args, "(s:)(i:)(s:)(i:)", &s1, &i1, &s2, &i2)
And then again while returning,
Py_BuildValue("sisi", arr_str1,arr_int1,arr_str2,arr_int2) ??
Infact if someone could in detail clarify the various PyArg_ParseTuple function that would be of great benefit. the Python C API, as i find it in the documentation, is not exactly a tutorial on things to do.
You can use PyArg_ParseTuple to parse a real tuple, that has a fixed structure. Especially the number of items in the subtuples cannot change.
As the 2.7.5 documentation says, your format "(s#:):#(i:)#(s#:):#(i:)#" is wrong since : cannot occur in nested parenthesis. The format "(sss)(iii)(sss)(iii)", along with total of 12 pointer arguments should match your arguments. Likewise for Py_BuildValue you can use the same format string (which creates 4 tuples within 1 tuple), or "(sss)[iii](sss)[iii]" if the type matters (this makes the integers to be in lists instead of tuples).
I am using what seems to be the exact usgae of PyArg_ParseTuple, yet the code is still failing to work. I am using python 2.7
This is my C code for the Python Extension I am writing:
static PyObject* tpp(PyObject* self, PyObject* args)
{
PyObject* obj;
PyObject* seq;
int i, len;
PyObject* item;
int arrayValue, temp;
if (!PyArg_ParseTuple(args, "O", &obj)){
printf("Item is not a list\n");
return NULL;
}
seq = PySequence_Fast(obj, "expected a sequence");
len = PySequence_Size(obj);
arrayValue = -5;
printf("[\n");
for (i = 0; i < len; i++) {
item = PySequence_Fast_GET_ITEM(seq, i);
// printf("%d : %d, PyArg: ", item, *item);
// PyArg_ParseTuple(item, "I", &temp);
PyObject* objectsRepresentation = PyObject_Repr(item);
const char* s = PyString_AsString(objectsRepresentation);
printf("%s\n", s);
PyObject* objType = PyObject_Type(item);
PyObject* objTypeString = PyObject_Repr(objType);
const char* sType = PyString_AsString(objTypeString);
printf("%s\n", sType);
if (PyArg_ParseTuple(item, "i", &arrayValue) != 0){
printf("%d\n", arrayValue);
printf("horray!\n");
}
}
Py_DECREF(seq);
printf("]\n");
printf("Item is a list!\n");
Py_RETURN_NONE;
}
Then I just build the extension and go to the terminal
import et
and then
et.tpp([1,2])
fails to print the line
if (PyArg_ParseTuple(item, "i", &arrayValue) != 0){
printf("%d\n", arrayValue);
printf("horray!\n");
}
I checked the type, as you can see in the code, of the elements in the list, and it prints 'int'. Yet for some reason PyArg_ParseTuple is having errors.
I need to be able to access information from lists in python to copy some data, pass it to my C code elsewhere, and then return the result to python.
Thank you so much!
The answer is to use long PyInt_AsLong(PyObject *io)
"long PyInt_AsLong(PyObject *io) Will first attempt to cast the object to a PyIntObject, if it is not already one, and then return its value. If there is an error, -1 is returned, and the caller should check PyErr_Occurred() to find out whether there was an error, or whether the value just happened to be -1."
This is from http://docs.python.org/2/c-api/int.html That is the official c python int objects documentation which has all relevant methods.
Unfortunately this returns only a long value. However, a simple cast should suffice if the expected values will be small.
PyArg_ParseTuple() is about parsing tuples only, as the name suggests. In your code, item is an int, not a tuple. In order to convert an int object to a C value, you need to use arrayValue = PyInt_AsLong(item). Note that it returns a C long, not an int, so you should declare arrayValue as a long.
(EDIT: previously I mentioned PyInt_FromLong by mistake.)