pythonc++compilationg++shared-objects

Compile C++ class with a header file to use it in python?


I have a my_class.h:

// my_class.h

namespace N
{
    class my_class
    {
    public:
        void hello_world();
    };
}

with a my_class.cpp file.

// my_class.cpp

extern "C" {
    #include "my_class.h"
}
#include <iostream>

using namespace N;
using namespace std;

void my_class::hello_world()
{
    cout << "Hello, World!" << endl;
}

I want to create a shared object my_class.so file to use it in python. Therefore, I am using the g++ compiler.

g++ -fPIC -shared -o my_class.so my_class.cpp

Using the shared object in python my_class.so

import ctypes

my_class = ctypes.cdll.LoadLibrary('./my_class.so')
my_class.hello_world

I get the following error message:

Exception has occurred: AttributeError
./my_class.so: undefined symbol: hello_world

I do not know how to interpret this.
Note:


Solution

  • Much to talk about, but I'll try to be brief:

    1. extern "C" is going to make those symbols available in the C-syntax. (You do want this)
    2. C-syntax does not support classes or namespaces.
    3. the python dynamic library loader is grabbing ALL the symbols - not just your class. (It seems there is some confusion there with the naming scheme)

    To Fix: Simply eliminate your class and namespaces (or add a C-API pass-through).

    my_class.h

    extern "C" {
       void hello_world();
    }
    

    my_class.cpp

    #include "my_class.h"
    #include <iostream>
    
    void hello_world()
    {
            std::cout<<"Hello, World" << std::endl;
    }
    

    After you build, use nm or objdump to verify that the symbol hello_world is defined and not mangled. Example:

    >> nm my_class.so | grep hello
    0000000000000935 T hello_world
    

    And your python code will need an open close parenthesis to tell it to execute the function:

    import ctypes
    
    my_class = ctypes.cdll.LoadLibrary('./my_class.so')
    my_class.hello_world()