使用 cython 包装 c++ DLL:所有字符串均为空
Wrapping a c++ DLL using cython: all strings are empty
我正在尝试使用cython包装用c ++编写的DLL。最后,我将无法访问源代码,所以C++源代码本身不能在编译包装器的过程中使用,.dll
、.lib
和.h
。一切都编译得很好。但是,我立即发现字符串表现不佳。 例如,dll返回简单字符串的函数无法正常工作:cython 代码总是得到空字符串。 我在窗口 7 上。我已经验证了以下内容。
- DLL 已由 Visual Studio 2015(即 v 1900)使用 2015 工具集在调试中构建模式。我尝试使用/MTd 和/MDd 标志进行编译。生成的 .lib 和.dll文件是与下面的所有其他文件放在同一个文件夹中。
-
我的python 3.5发行版也是由VS 2015构建的,用于32位。
$ python -iu Python 3.5.1 (v3.5.1:37a07cee5969, Dec 6 2015, 01:38:48) [MSC v.1900 32 bit (Intel)] on win32
-
当我使用包含返回字符串的此类函数的虚拟 c++ 源代码进行编译时,它只是工作。使用 dll 它不起作用。
setup.py:
from distutils.core import setup
from Cython.Build import cythonize
setup(ext_modules=cythonize(
"test.pyx", # our Cython source
))
test.pyx:
# distutils: language = c++
# distutils: libraries = MyDLL
# distutils: include_dirs = .
# distutils: library_dirs = .
from libcpp.string cimport string
cdef extern from "MyDLL.h" namespace "somenamespace":
int ReturnSomeInt()
string ReturnSomeString()
def run():
cdef string s = string(b'abcdefg')
print(s)
cdef int i = ReturnSomeInt()
print(i)
cdef string problem = ReturnSomeString()
print(problem)
MyDLL.h:
__declspec(dllexport) int ReturnSomeInt();
__declspec(dllexport) std::string ReturnSomeString();
用于编译 MyDLL 的C++代码片段:
__declspec(dllexport) int ReturnSomeInt() { return 42; }
__declspec(dllexport) std::string ReturnSomeString() { cout << "debug..." << endl; return "Hello world!"; }
main.py:
from test import run
run()
我使用命令编译
$ python setup.py build_ext --inplace --force && python -u main.py
运行此打印
b'abcdefg'
42
debug... # printed by the dll function ReturnSomeString()
b'' # Should've printed: b'Hello World!'
我们可以验证 MyDLL 中的 ReturnSomeString() 是否确实被调用,因为它会向 stdout 发送一些文本。
我没有检查什么?
多亏了@hakala指出的这个答案,我发现调试/发布模式很重要。我没想到可以。我引用:
C++标准库有自己的一组 ABI 问题。没有 保证给定的 STL 类型在内存中的布局方式相同, 也不能保证给定的 STL 类具有相同的大小 一个实现到另一个实现(特别是,调试版本可能会将 将额外的调试信息转换为给定的 STL 类型)。因此,任何 STL 容器必须先解压缩为基本类型,然后才能 越过 DLL 边界并在另一侧重新打包。
实际上,在发布模式下编译 DLL 使 OP 中的示例起作用。