首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >使用cython包装c++ DLL :所有字符串都为空

使用cython包装c++ DLL :所有字符串都为空
EN

Stack Overflow用户
提问于 2016-07-15 10:07:01
回答 1查看 2.1K关注 0票数 1

我试图使用cython包装用c++编写的动态链接库。最后,我将无法访问源代码,因此c++源代码本身不能用于编译包装器、jus .dll.lib.h。一切都很好。然而,我立即发现字符串的表现并不好。例如,返回一个简单字符串的dll函数不能正常工作: cython代码总是得到一个空字符串。我在windows 7上,我已经验证了以下内容。

  • DLL是由Visual 2015 (即v 1900)生成的,其2015工具集处于调试模式。我尝试使用/MTd和/MDd标志进行编译。生成的.lib和.dll文件与下面的所有其他文件放在同一个文件夹中。
  • 我的python3.5发行版也是在VS 2015之前构建的,只需32位。 $ python Python3.5.1 (v3.5.1:37a07cee5969,2015年12月6日,01:38:48) MSC v.1900 32位(英特尔) on win32
  • 当我使用一个包含返回字符串的函数的虚拟c++源代码进行编译时,它只是起作用了。使用dll它不起作用。

setup.py:

代码语言:javascript
运行
复制
from distutils.core import setup
from Cython.Build import cythonize

setup(ext_modules=cythonize(
    "test.pyx",                 # our Cython source
))

test.pyx:

代码语言:javascript
运行
复制
# 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:

代码语言:javascript
运行
复制
__declspec(dllexport) int ReturnSomeInt();
__declspec(dllexport) std::string ReturnSomeString();

用于编译C++的MyDLL代码片段:

代码语言:javascript
运行
复制
__declspec(dllexport) int ReturnSomeInt() { return 42; }
__declspec(dllexport) std::string ReturnSomeString() { cout << "debug..." << endl; return "Hello world!"; }

main.py:

代码语言:javascript
运行
复制
from test import run
run()

我使用命令进行编译

代码语言:javascript
运行
复制
$ python setup.py build_ext --inplace --force && python -u main.py

运行此打印

代码语言:javascript
运行
复制
b'abcdefg'
42
debug... # printed by the dll function ReturnSomeString()
b'' # Should've printed: b'Hello World!'

我们可以验证是否真的调用了来自MyDLL的MyDLL(),因为它向stdout发送了一些文本。

我有什么没查的?

EN

回答 1

Stack Overflow用户

发布于 2016-07-15 11:33:11

多亏了@hakala所指出的this answer,我发现调试/发布模式很重要。我并没有想到它能做到。我引述如下:

C++标准库有它自己的一组ABI问题。不能保证给定的STL类型在内存中的布局方式相同,也不能保证给定的STL类从一个实现到另一个实现具有相同的大小(特别是,调试构建可以将额外的调试信息放入给定的STL类型)。因此,任何STL容器都必须在通过DLL边界并在另一侧重新打包之前被解压缩为基本类型。

实际上,在发布模式下编译DLL使OP中的示例工作起来。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/38393393

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档