所以我想做的事情相当简单,我想使用 swig 在 Python 中访问一个 C++ 类。我已经设法为独立应用程序做到这一点,但这还不够。
我所拥有的:一个相当庞大的 C++ 库,它使用 SCons 编译。这会生成一个静态 (lib---.a) 库。我还有一个使用一些库功能的小型 C++ 类。
我试图做的是让 SCons 编译所有内容,包括我的自定义类,然后执行 swig 魔术。我定义了一个 swig 接口文件,包括我的头文件的结构,我也包含在 swig 接口文件中。
在头文件中有对库的依赖,但由于这些已经被编译(到静态库中),swig 找不到它。更换 SCons 不是一种选择。但是,我可以制作一个动态库而不是静态库。
所以我的问题归结为:是否有在 SCons 中使用 Swig 的正确方法,或者,您能否以某种方式将库依赖项包含为现有动态库?此外,我可以(使用 SCons)将我的自定义类编译为对象 (.o) 文件或动态库 (.so)。关于动态库,这就是事情变得混乱的地方,因为这也是 swig 生成的(?),或者至少是由某人生成的。
这甚至有意义吗?我显然如履薄冰,不一定知道我在说什么。
下面是 c++ 头文件和 swig 接口,我排除了 c++ 源代码,因为它感觉多余。
我的头文件:
#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>);
};
我对应的swig接口文件:
%module Ops
%{
#include "Ops.h"
%}
%include "Ops.h"
class Ops{
public:
Ops(std::string, uint64_t, std::string);
~Ops();
...
void makeLeader();
void getLeader();
};
使用的命令:
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;
谢谢。#swig
编辑:
我包括由 SConstruct 调用的 SConscript。
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)
])
编辑2:
我更新了 SContruct env 声明来为 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)
编译生成的 Ops_wrap.cc 文件时,它给了我很多类型转换警告,但仍然完成编译,例如
build/Impl/Ops_wrap.cc:654:23: warning: conversion to ‘unsigned char’ from ‘int’ may alter its value [-Wconversion]
uu = ((d - '0') << 4);
当尝试通过生成的 Ops.py 文件访问 Ops 类时,导入 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
未定义的符号对应于库“LogCabin::Client::Tree::readEx()”中的一个函数。想法?