So what I want to do is fairly straight forward, I want to access a C++ class in Python using swig. I've managed to do this for stand alone applications but that's not enough.
What I have: a fairly huge C++ library which is compiled using SCons. This generates a static (lib---.a) library. I also have a small C++ class using some of the library functionality.
What I tried to do was letting SCons compile everything, including my custom class, and then do the swig magic. I defined an swig interface file including the structure of my header file which I also included in the swig interface file.
In the header file there are dependencies to the library, but since these already have been compiled (into the static lib) swig can't find it. Replacing SCons is not an option. However, I can make a dynamic library instead of a static one.
So my question boils down to this: is there a proper way of using Swig inside SCons, or, can you somehow include the library dependency as an existing dynamic library? Furthermore, I can (using SCons) either compile my custom class into an object (.o) file or a dynamic library (.so) as well. Regarding the dynamic library, this is where things get messy since this is also what swig generates (?), or at least generated by someone.
Does this even make sense? I'm clearly on thin ice and don't necessarily know what I'm talking about.
Below are the c++ header and swig interface, I excluded c++ source since it felt redundant.
My Header File:
#include "../include/LogCabin/Client.h"
#include "../include/LogCabin/Debug.h"
#include "../include/LogCabin/Util.h"
class Ops{
private:
void dumpTree(std::string);
void dumpTreeLocal(std::string);
public:
Ops(std::string, uint64_t, std::string);
~Ops();
...
void makeLeader();
void getLeader();
int reconfigure(std::vector<std::string>);
};
My corresponding swig interface file:
%module Ops
%{
#include "Ops.h"
%}
%include "Ops.h"
class Ops{
public:
Ops(std::string, uint64_t, std::string);
~Ops();
...
void makeLeader();
void getLeader();
};
Commands used:
swig -c++ -python Ops.i;
g++ -std=c++11 -c -fPIC Ops_wrap.cxx -I/usr/include/python2.7 -I/usr/lib/python2.7;
g++ -std=c++11 -shared -Wl,-soname,_Ops.so -o _Ops.so Ops.o Ops_wrap.o;
Thanks. #swig
EDIT:
I include the SConscript called by SConstruct.
Import('env', 'object_files')
libs = [ "pthread", "protobuf", "rt", "cryptopp" ]
src = [
"Ops.cc",
"Ops.i"
]
/*object_files['Impl'] = env.StaticObject(src)*/
env.Default([
env.SharedLibrary("Ops", src,
LIBS = libs)
])
Edit2:
I updated the SContruct env declaration to set some parameters for swig.
env = Environment(options = opts,
SWIGFLAGS=['-c++','-python'],
CPPPATH=["/usr/include/python2.7"]),
LIBPATH=["/usr/lib/python2.7"]),
SHLIBPREFIX="",
tools = ['default', 'protoc', 'packaging'],
ENV = os.environ)
When compiling the generated Ops_wrap.cc file it gives me a lot of type cast warnings but still finish the compilation, e.g.
build/Impl/Ops_wrap.cc:654:23: warning: conversion to ‘unsigned char’ from ‘int’ may alter its value [-Wconversion]
uu = ((d - '0') << 4);
When trying to access the Ops class via the generated Ops.py file it gives me error when importing Ops:
Traceback (most recent call last):
File "test.py", line 3, in <module>
import Ops
ImportError: /home/erneborg/Applications/coherent/logcabin/build/Impl/Ops.so: undefined symbol: _ZNK8LogCabin6Client4Tree6readExERKSs
The undefined symbol corresponds to a function in the library "LogCabin::Client::Tree::readEx()". Thoughts?