Use another language to call a function: Difference between revisions
Content deleted Content added
Begin python solution. Please simplify, if possible. |
|||
Line 446: | Line 446: | ||
=={{header|Python}}== |
=={{header|Python}}== |
||
Our embedded python function a) uses information from the main routine in c, and b) determines the information to populate the result returned to the main routine. This, I believe, fulfills the task requirement. The modifications and compilation are shown for Ubuntu linux Autumn 2011 version, with python3. It's easier to call a dynamic library from python using the ctypes module. Consider using <tt>PyRun_SimpleString</tt> to have main.c call python calling back to c. |
|||
<lang python> |
|||
# store this in file rc_embed.py |
|||
def query(buffer_length): |
|||
message = b'Here am I' |
|||
L = len(message) |
|||
n = min(L,buffer_length) |
|||
#print(message[:n]) |
|||
return bytes(message[:n]) |
|||
</lang> |
|||
main.c |
|||
<lang c> |
|||
#if 0 |
|||
//I rewrote the driver according to good sense, my style, |
|||
//and discussion --Kernigh 15:45, 12 February 2011 (UTC). |
|||
#endif |
|||
#include<stdio.h> |
|||
#include<stdlib.h> |
|||
#include<string.h> |
|||
int main(int argc,char*argv[]) { |
|||
char Buffer[1024], *pc; |
|||
unsigned Size = sizeof(Buffer); |
|||
if (!Query(Buffer,&Size)) |
|||
fputs("Failed to call Query",stdout); |
|||
else |
|||
for (pc = Buffer; Size--; ++pc) |
|||
putchar(*pc); |
|||
putchar('\n'); |
|||
return EXIT_SUCCESS; |
|||
} |
|||
</lang> |
|||
In Query.c I don't promise to have tested every case with missing module, missing function, or to have used <tt>Py_DECREF</tt> correctly. |
|||
<lang c> |
|||
#include<stdio.h> |
|||
#include<stdlib.h> |
|||
#include<string.h> |
|||
#include<Python.h> |
|||
int Query(char*Data,unsigned*Length) { |
|||
char *module = "rc_embed", *function = "query"; |
|||
PyObject *pName, *pModule, *pFunc, *pResult, *pArgs, *pLength; |
|||
long result = 0; |
|||
if (!Py_IsInitialized()) |
|||
Py_Initialize(); |
|||
pName = PyUnicode_FromString(module); |
|||
pModule = PyImport_Import(pName); |
|||
Py_DECREF(pName); |
|||
if (NULL == pModule) { |
|||
PyErr_Print(); |
|||
fprintf(stderr,"Failed to load \"%s\"\n",module); |
|||
return 0; |
|||
} |
|||
pFunc = PyObject_GetAttrString(pModule,function); |
|||
if ((NULL == pFunc) || (!PyCallable_Check(pFunc))) { |
|||
if (PyErr_Occurred()) |
|||
PyErr_Print(); |
|||
fprintf(stderr,"Cannot find function \"%s\"\n",function); |
|||
if (NULL != pFunc) |
|||
Py_DECREF(pFunc); |
|||
Py_DECREF(pModule); |
|||
return 0; |
|||
} |
|||
pArgs = PyTuple_New(1); |
|||
pLength = PyLong_FromUnsignedLong((unsigned long)(*Length)); |
|||
if (NULL == pLength) { |
|||
Py_DECREF(pArgs); |
|||
Py_DECREF(pFunc); |
|||
Py_DECREF(pModule); |
|||
return 0; |
|||
} |
|||
PyTuple_SetItem(pArgs,0,pLength); |
|||
pResult = PyObject_CallObject(pFunc, pArgs); |
|||
if (NULL == pResult) |
|||
result = 0; |
|||
else if (!PyBytes_Check(pResult)) { |
|||
result = 0; |
|||
Py_DECREF(pResult); |
|||
} else { |
|||
*Length = (unsigned)PyBytes_Size(pResult); |
|||
strncpy(Data,PyBytes_AsString(pResult),*Length); |
|||
Py_DECREF(pResult); |
|||
result = 1; |
|||
} |
|||
Py_DECREF(pArgs); |
|||
Py_DECREF(pFunc); |
|||
Py_DECREF(pModule); |
|||
Py_Finalize(); |
|||
return result; |
|||
} |
|||
</lang> |
|||
Compilation, linkage, execution. Note the python tools used to extract the correct flags. |
|||
<lang bash> |
|||
$ make main.o |
|||
cc -c -o main.o main.c |
|||
$ D=$( dirname $( which python3 ) ) |
|||
$ gcc $( $D/python3.2-config --cflags ) -c Query.c |
|||
In file included from /usr/include/python3.2mu/Python.h:8:0, |
|||
from Q.c:18: |
|||
/usr/include/python3.2mu/pyconfig.h:1173:0: warning: "_POSIX_C_SOURCE" redefined [enabled by default] |
|||
/usr/include/features.h:214:0: note: this is the location of the previous definition |
|||
$ gcc -o main main.o Query.o $( $D/python3.2-config --ldflags ) |
|||
$ ./main |
|||
Here am I |
|||
$ |
|||
</lang> |
|||
=={{header|Tcl}}== |
=={{header|Tcl}}== |