Marco
Marco

Reputation: 377

Loading C++ class in Python

I'm trying to import a C++ class in Python. I know I could use BoostPython, SWIG or Cython, but just for didatical purposes I'm trying to manually export C++ methods and functions with extern "C". In a nutshell, I'm trying to replicate this.

My enviroment is Windows 10, with Anaconda 3 and Python 3.6. I've installed mingw64 4.8.3 as C/C++ compiler.

This is my foo.cpp:

#include <iostream>
// A simple class with a constuctor and some methods...
class Foo
{
    public:
        Foo(int);
        void bar();
        int foobar(int);
    private:
        int val;
};
Foo::Foo(int n)
{
    val = n;
}
void Foo::bar()
{
    std::cout << "Value is " << val << std::endl;
}
int Foo::foobar(int n)
{
    return val + n;
}
// Define C functions for the C++ class - as ctypes can only talk to C...
extern "C"
{
    Foo* Foo_new(int n) {return new Foo(n);}
    void Foo_bar(Foo* foo) {foo->bar();}
    int Foo_foobar(Foo* foo, int n) {return foo->foobar(n);}
}

I've compiled in this way: g++ -c -fPIC foo.cpp -o foo.o. The output is:

foo.cpp:1:0: warning: -fPIC ignored for target (all code is position independent) [enabled by default]
#include <iostream>
^

Then, I've compiled in this way: g++ -shared -Wl,-soname,libfoo.dll -o libfoo.dll foo.o getting no errors/warnings. The file libfoo.dll has appared in the folder.

When I try in Python:

import ctypes
lib = ctypes.windll.LoadLibrary('libfoo.dll')

I get the error OSError: [WinError 126] the specified module could not be found. My Python working directory is the libfoo.dll folder.

I tried to create a simple C-HelloWorld library: I compiled in the same way (a part gcc instead of g++) and I succeded in loading it into Python.

Where is the problem? Is it in the compilation instructions? Or in the code?

Upvotes: 5

Views: 1001

Answers (1)

Marco
Marco

Reputation: 377

I've found a solution starting from @Scheff comment.

On Linux (I've tried on Ubuntu 16, GCC 4.4.0 and Python 3.6), my question code works well without modifications (both on the code and on the compilation instructions).

On Windows, I modified the extern "C" block in this way:

extern "C"
{
     __declspec(dllexport) Foo* Foo_new(int n) {return new Foo(n);}
     __declspec(dllexport) void Foo_bar(Foo* foo) {foo->bar();}
     __declspec(dllexport) int Foo_foobar(Foo* foo, int n) {return foo->foobar(n);}
}

and I recompiled as before.

Thereafter I was able to import the module and the C++ class as described in the question link.

For implementing the C++ print function please see this question.

Upvotes: 3

Related Questions