0

I am facing some problems with calling the class from an address given by the pointer. I need to call c++ in python. Here is my cpp code

extern "C" {
    Pancreas* SeedAndGrowToStartVolume(double p0, double psc, int dmax, int gage, int page, double startVolume)
    {

        Params* parameters = new Params(p0, psc, dmax, gage, page);
        vector<Cell*> empty;
        Pancreas* pancreas = new Pancreas(empty, parameters);
        pancreas->CreateInitialTumour();

        double volume = 0;
        int days = 0;
        while (volume < startVolume && days < 200)
            volume = pancreas->SimulateOneDay(days++);

        fprintf(stdout,"%x\n",days);
        fprintf(stdout,"%x, %u,%d\n",pancreas,pancreas,pancreas);
        
        return pancreas;
    }

}

when I use python to call SeedAndGrowToStartVolume, it returns an integer, which is the address of pancreas. Here is the python code

from ctypes import *
import os.path

file_path = os.path.abspath('Model.so')
testdll = cdll.LoadLibrary(file_path)

testdll.SeedAndGrowToStartVolume.argtypes = [c_double, c_double, c_int, c_int, c_int, c_double]
testdll.SeedAndGrowToStartVolume.restypes = py_object

## pf is an address
pf = testdll.SeedAndGrowToStartVolume(0.5,1e-5,50,150,2,100)

I want to call a function in pancreas class. But I only have an integer. Here is .h file that contains pancreas class. The function I want to call is double SimulateOneDay(int day)

extern "C" {
class Pancreas
{
public:
    double SimulateOneDay(int day)
    {
        DetermineNeighbours();

        for (int hour = 1; hour <= Params::tinterval; hour++)
        {
            //parameters->created = parameters->opportunities = 0;
            SimulateOneHour();
            //printf("day %d, hour %d, %d of %d created\n", day, hour, parameters->created, parameters->opportunities);
        }
        return TumourVolume();
    }
    void UpdateParameters(Params* parameters)
    {
        this->parameters = parameters;
    }
};
}

  • `extern "C"` doesn't have kind of power you are trying to get from it here. It doesn't apply to class member functions (AKA methods). What you are trying to do is interact with C. C has no concept of classes (let alone methods). If you want to be able to access this from C, you will need to add some kind of wrapper function external to any class. – Jason Mar 28 '22 at 13:38
  • Write a C function `double simulateOneDay(Pancreas* p, int day) { return p->SimulateOneDay(day); }`, and call that from Python. – molbdnilo Mar 28 '22 at 13:46
  • I am using macOS. If I did not add extern "C", the code will not compile for some reason. Is there any documentation for the wrapper function? – john wang Mar 28 '22 at 15:18
  • FYI, `std::vector` is C++ only and not C. Is there a C interface for `std::vector`??? Usually you want only C interfaces in an `extern C` statement. – Thomas Matthews Mar 28 '22 at 15:32
  • Hmmm... is there another way to call c++ function on Python? – john wang Mar 28 '22 at 15:46
  • @johnwang Yes, [pybind11](https://github.com/pybind/pybind11) or [boost.Python](https://www.boost.org/doc/libs/1_78_0/libs/python/doc/html/tutorial/index.html) are two names that often come. – Neitsa Mar 28 '22 at 17:23
  • For one of the errors in your code: [\[SO\]: C function called from Python via ctypes returns incorrect value (@CristiFati's answer)](https://stackoverflow.com/questions/58610333/c-function-called-from-python-via-ctypes-returns-incorrect-value/58611011#58611011). – CristiFati Mar 28 '22 at 20:17
  • FYI, `py_object` as your `.restype` is incorrect. Use `c_void_p` or an opaque pointer like `class Pancreas: pass` and `.restype = POINTER(Pancreas)`. – Mark Tolonen Mar 29 '22 at 00:05

0 Answers0