2

I am using ctypes to call a C code:

mysum.cpp

//global variables and required functions are defined
int mysum(int ECG_sample) 
{
   int HR;
   ecg_wave_sample = ECG_sample;
   Filter_CurrentECG_sample(&ecg_wave_sample, &ecg_filterout);  
   Calculate_HeartRate(ecg_filterout,&global_HeartRate); // calculate HeartRate
   HR = global_HeartRate;
   return HR;
}

g++ -shared -o mysum.so -fPIC mysum.cpp used to create the .so file

Python wrapper:

libname = '/home/yasaswini/hp2-notebooks/notebooks/Algorithm_testing_on_database/mysum_example  /mysum.so'
libdir = './'
lib=ctl.load_library(libname, libdir)
py_add_one = lib.mysum
py_add_one.restype = ctypes.c_int
py_add_one.argtypes = [ctypes.c_int]
sample = -145
results = py_add_one(sample)

I am getting this error

 AttributeError Traceback (most recent call last) <ipython-input-75-858227ec99e5> in <module>
  6 # 1. open the shared library
  7 #mylib = ctypes.CDLL(libfile)
  ----> 8 py_add_one = lib.mysum
  9 
  10 # 2. tell Python the argument and result types of function mysum

  ~/anaconda3/lib/python3.7/ctypes/__init__.py in __getattr__(self, name)
   375         if name.startswith('__') and name.endswith('__'):
   376             raise AttributeError(name)
   --> 377         func = self.__getitem__(name)
   378         setattr(self, name, func)
   379         return func

   ~/anaconda3/lib/python3.7/ctypes/__init__.py in __getitem__(self, name_or_ordinal)
  380 
  381     def __getitem__(self, name_or_ordinal):
  --> 382         func = self._FuncPtr((name_or_ordinal, self))
  383         if not isinstance(name_or_ordinal, int):
  384             func.__name__ = name_or_ordinal

  AttributeError: /home/yasaswini/hp2-notebooks/notebooks/Algorithm_testing_on_database /mysum_example/mysum.so: undefined symbol: mysum

Can someone point out what exactly I am doing wrong here?

10

2 Answers 2

5

This is probably related to C++ name mangling.

You need to add extern to the definition of your function in mysum.cpp since you are using C++ (g++). In your case:

extern "C" int mysum(int ECG_sample) 
{
   ...
}

More info on name mangling

See also

https://stackoverflow.com/a/11237254/7919597

https://stackoverflow.com/a/34380673/7919597

Sign up to request clarification or add additional context in comments.

Comments

0

I used the logic given here.

.c file:

int simple_function(int ECG_samples) 
{
    ecg_wave_sample = ECG_samples;
    ECG_ProcessCurrSample(&ecg_wave_sample, &ecg_filterout); 
    QRS_Algorithm_Interface(ecg_filterout);
    printf("HR:%d\n",ecg_wave_sample);
    return global_HeartRate;  
}

Python script:

import numpy
def call_function_with_no_args(libc): 
ECG_samples = [3,4,6,6,9,11,13,17,18,21,23,24,28,30,33,35,36,36]
while(1):

    for i in range (len(ECG_samples)):
        value = print(libc.simple_function(ECG_samples[i]))
    print()
return value

if __name__ == "__main__":
# load the shared library into c types.
    libname = os.path.abspath(os.path.join(os.path.dirname(__file__),
                                       "libclib1.so"))
    LIBC = ctypes.CDLL(libname)


call_function_with_no_args(LIBC)

I think this is the best way of working with ctypes. Its simple and easy to understand. The Makefile generates the .so file. Thank you for the help. :-)

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.