ctypes如何将字符串从python传递到c ++函数,以及如何将字符串从c ++函数返回到python

icy*_*ndy 6 c++ python string ctypes

我想从python调用一个c ++函数,这个c ++函数将char*作为参数,并返回字符串.以下是我的代码.

wrapper.cpp

#include <Python.h>
#include <string>
#include <iostream>

using namespace std;

extern "C"
string return_string(char* name){
    cout<<strlen(name)<<endl;
    cout<<name<<endl;
    string s = "hello ";
    s += name;
    return s;
}
Run Code Online (Sandbox Code Playgroud)

将wrapper.cpp编译为example.so

g++ -fPIC wrapper.cpp -o example.so -shared -I/usr/include/python2.7/
Run Code Online (Sandbox Code Playgroud)

wrapper.py

import os
from ctypes import *

lib = cdll.LoadLibrary('./example.so')
lib.return_string.restype = c_char_p
lib.return_string.argtypes = [c_char_p]
name = create_string_buffer("Tom")
s = lib.return_string(name);
print s
print name
Run Code Online (Sandbox Code Playgroud)

这是我的输出

18
??H?L?l???A???
1
<ctypes.c_char_Array_4 object at 0x7f5f480be710>
Run Code Online (Sandbox Code Playgroud)

如何使其工作?

aba*_*ert 11

这与ctypes无关; 您的C++代码本身无效.您无法定义extern "C"返回a 的函数string.

在使用相同库的C++程序的快速测试中,它还会打印垃圾.

我还写了一个C程序,它定义了一个调用string相同布局的东西,std::string所以我可以编译它,看看会发生什么; 它还会打印垃圾,然后会出现段错误~string.

因此,Python程序也打印垃圾也就不足为奇了.

一切都很小,一切正常:

extern "C"
const char *return_string(char* name){
    cout<<strlen(name)<<endl;
    cout<<name<<endl;
    static string s = "hello ";
    s += name;
    return s.c_str();
}
Run Code Online (Sandbox Code Playgroud)

我得到这个输出:

3
Tom
hello Tom
<ctypes.c_char_Array_4 object at 0x11011c7a0>
Run Code Online (Sandbox Code Playgroud)

(或者,从C++版本开始,同样的事情,但在最后一行使用"Tom".)

当然,由于显而易见的原因,这不是一个非常好的解决方案,但它表明返回string是问题所在.

当我尝试编译你的C++代码时,g ++ - 4.5和clang-apple-4.0都提醒我这个问题(尽管g ++ - apple-4.2没有,除非我添加了一个额外的-W标志).当编译器给你一个警告时,这通常是"为什么我的代码做错了,即使它编译"的答案.

您的代码还有一些问题:

  • 您不能在.cpp文件中使用Python中的任何内容.一般来说,使用的全部意义在于ctypes您的C或C++代码不必了解Python; 这是你的Python代码知道它.所以,不要包含或链接.
  • char*如果你不打算修改它,那么采用非const通常是一个坏主意.我的C++司机曾与调用它const_cast<char*>(name.c_str()),而不是只name.c_str().此外,这可以防止编译器注意到您正在做的其他事情.

这是我上面提到的C++驱动程序:

#include <iostream>
#include <string>
using namespace std;

extern "C" string return_string(char* name);

int main(int argc, char *argv[]) {
  string name("Tom");
  string s(return_string(const_cast<char *>(name.c_str())));
  cout << s << "\n";
  cout << name << "\n";
  return 0;
}
Run Code Online (Sandbox Code Playgroud)

此外,如果我使用不同的优化设置或稍微重新组织代码,在我的C++驱动程序中,有时您的代码实际上有效,有时它会打印垃圾,有时会出现段错误.我的第一个猜测是,它取决于~string电话内联的位置 - 但实际上,细节并不重要; 代码不应该工作,它不会,所以谁在乎为什么?