I have a Python application interfacing with C++ via Boost Python. The C++ segment of the application is built using Bjam (Bjam make file can be found at bottom of question). The C++ compiles (and appears to link) fine.
Shortly after the Python executes it complains about an undefined symbol, referenced from a C++ file. This C++ file includes a C++ header where the undefined symbol is declared. If I remove the reference to the problematic variable, the code continues executing fine.
If I run nm
on the library it lists the symbol with a U (undefined).
Could someone help why I am receiving this undefined symbol runtime error? I think it's probably because I haven't included something in my gcc path?
The python code calls a C++ method, which creates an object using a variable defined in C_NAMESPACE
:
/dir/folder1/bridge.cpp
#include "c.h"
namespace CPP
{
void calledByPython()
{
MyClass x(C_NAMESPACE::VAR);
// continues
}
}
which is located in the header file c.h:
/dir/folder2/c.h
#ifndef C_H
#define C_H
namespace C_NAMESPACE
{
extern const std::string VAR;
}
where the source file looks like:
/dir/folder2/c.cpp
#include "c.h"
namespace
{
const std::string VAR = "something";
}
and I am building this C++ using bjam:
import python ;
lib gbclientlib : : <name>gbclient <search>$(gbclient_dir)/lib <link>static ;
explicit gbclientlib ;
project gb
: requirements
<location>.
<cxxflags>"-std=c++11 -Wno-deprecated -I /dir/folder1/ -I /dir/folder2/"
;
python-extension _bridge : bridge.cpp ;
When C++ code gets compiled, the names get mangled. C code does not get mangled. C++ name-mangling poses a problem for exposing functions...anywhere really.
The solution to the problem is to wrap C++ calls under C-like interfaces so that the name doesn't get mangled. For example, to return your std::string VAR
to C (and ultimately Python):
extern "C"
{
const char* get_var(void){ return VAR.c_str();}
}
Boost.Python knows all this and tries to make things easier for you by hiding the extern "C" bits with macros like BOOST_PYTHON_MODULE
The extern "C"
trick is used predominately to expose C++ code to other languages. (C#, however, has CLR and PInvoke)