I want to call a c++ function from python, this c++ function takes char* as parameter, and return string. Below is my code.
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;
}
compile wrapper.cpp to example.so
g++ -fPIC wrapper.cpp -o example.so -shared -I/usr/include/python2.7/
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
here is my output
18
��H�L�l���A���
1
<ctypes.c_char_Array_4 object at 0x7f5f480be710>
How to make it works?
This has nothing to do with ctypes; your C++ code is invalid in itself. You can’t define an
extern "C"function that returns astring.In a quick test with a C++ program that uses the same library, it also prints garbage.
I also wrote a C program that defines something called
stringwith the same layout asstd::stringjust so I could compile it and see what happens; it also prints garbage, and then it segfaults in~string.So, it’s not surprising that the Python program also prints garbage.
With a minor change, everything works:
I get this output:
(Or, from the C++ version, the same thing but with “Tom” in the last line.)
Of course for obvious reasons this isn’t a very good solution, but it shows that returning
stringis the problem.Both g++-4.5 and clang-apple-4.0 warned me about exactly this problem when I tried to compile your C++ code (although g++-apple-4.2 didn’t, unless I added an extra -W flag). When the compiler gives you a warning, that’s often the answer to “why does my code do the wrong thing even though it compiles”.
A few other things wrong with your code:
ctypesis so your C or C++ code doesn’t have to know anything about Python; it’s your Python code that knows about it. So, don’t include or link.char*if you aren’t planning to modify it. My C++ driver had to call it withconst_cast<char*>(name.c_str())instead of justname.c_str(). Also, this can prevent the compiler from noticing other things that you’re doing.Here’s the C++ driver I mentioned above:
Also, if I play around with different optimization settings or reorganize the code a bit, in my C++ driver, sometimes your code actually works, sometimes it prints garbage, and sometimes it segfaults. My first guess would be that it depends where the
~stringcall gets inlined—but really, the details don’t matter; the code shouldn’t work, and it doesn’t, so who cares why?