Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Calling C function from Python (No Return Value)

Tags:

python

c

swig

I used SWIG to connect my C++ program with Python. From cFunctions.py I call C function named checkVal like following:

lib = cdll.LoadLibrary('./test.so')

    xml_bytesTrx = bytearray(b'<xml>...</xml>')
    a1  = (ctypes.c_byte*513)(*xml_bytesTrx)

    class EFT_TRX(Structure):
        _fields_ = [
                    ("a2",c_ulong),
                    ("a3",c_char*16),
                    ("a4",c_char*4),
                    ("a5",c_ushort),
                    ("a6",c_char*41),
                    ("a7",c_char*13),
                    ("a8",c_char*21),
                    ("a1",c_byte*513)
                    ]


    Trx = EFT_TRX(0,"0",'CHF',0,'4506445638161117',"123456123456","202020",
                   a1)
def check(arg1, arg2):

    eftTransactionRes = lib.checkVal(arg1,arg2,Trx.a4,Trx.a5,
                                   Trx.a6,Trx.a7,Trx.a8,
                                   Trx.a1)

    Trx.a3 = arg2
    return eftTransactionRes

And in C header file (test.h) is defined like following:

long TEST_API checkVal(             
        _IN____ const unsigned long a2, 
        _INOUT_ char a3[16], 
        _IN____ const char a4[4], 
        _IN____ const unsigned short a5, 
        _IN____ const char a6[41], 
        _IN____ const char a7[13], 
        _IN____ const char a8[21],
        _INOUT_ char a1[513]
        );

Now I wrote a test Python code to call C functions (accessible from cFunctions.py). The issue is that , when I call "check" from my test code ( cFunctions.check(10,20) ) I reach it, but it never returns anything!

But if I call check from within cFunctions.py itself like this:

check(10,Trx.a2)

It returns the result. What am I doing wrong? Why check doesn't return anything when I'm calling it from my test.py ?

like image 633
AJ-B29 Avatar asked Apr 28 '15 14:04

AJ-B29


1 Answers

Does this help? A little Googling led me here!

Calling C functions from Python - By Christian Stigen Larsen

Reproducing the above link here for reference. I have not tested the code listed here. Also all the credit belongs to the author of the above link.

Here’s a small tutorial on how to call your C functions from Python.

Let's make some simple functions in C. We'll call the file

myModule.c

#include <Python.h>

/*
 * Function to be called from Python
 */
static PyObject* py_myFunction(PyObject* self, PyObject* args)
{
  char *s = "Hello from C!";
  return Py_BuildValue("s", s);
}

/*
 * Another function to be called from Python
 */
static PyObject* py_myOtherFunction(PyObject* self, PyObject* args)
{
  double x, y;
  PyArg_ParseTuple(args, "dd", &x, &y);
  return Py_BuildValue("d", x*y);
}

/*
 * Bind Python function names to our C functions
 */
static PyMethodDef myModule_methods[] = {
  {"myFunction", py_myFunction, METH_VARARGS},
  {"myOtherFunction", py_myOtherFunction, METH_VARARGS},
  {NULL, NULL}
};

/*
 * Python calls this to let us initialize our module
 */
void initmyModule()
{
  (void) Py_InitModule("myModule", myModule_methods);
}

Compiling dynamic libraries on Mac OS X is different from the usual gcc -shared you might be used to:

gcc -dynamiclib -I/usr/include/python2.3/ -lpython2.3 -o myModule.dylib myModule.c

Now you have to do something awkward; rename myModule.dylib to myModule.so, so that Python will find the correct file (this is a bug in Python, it should've been fixed, but that's as far as I know):

mv myModule.dylib myModule.so

If you are using a system that supports -shared you can simply do this:

gcc -shared -I/usr/include/python2.3/ -lpython2.3 -o myModule.so myModule.c

On Windows you can reportedly type

gcc -shared -IC:\Python27\include -LC:\Python27\libs myModule.c -lpython27 -o myModule.pyd

Here's a simple program in Python to call your functions:

from myModule import *

print "Result from myFunction:", myFunction()
print "Result from myOtherFunction(4.0, 5.0):", myOtherFunction(4.0, 5.0)

The output is:

Result from myFunction(): Hello from C!
Result from myOtherFunction(4.0, 5.0): 20.0

If you are going to make bigger libraries available from Python I strongly suggest you check out SWIG or Boost Python.

like image 185
Curious Avatar answered Oct 22 '22 11:10

Curious