如何将const char*从python传递给c函数

Mah*_*sia 4 python ctypes python-c-api

ctypes在Python中使用它来打开一个用C++编写的文件.

我的C++代码:

extern "C" {
void openfile(const char *filename) {
    cout<<"File to open for writing = " <<filename<<endl;
    FILE *fp = fopen(filename,"w");
    fprintf(fp,"writing into file");
    fclose(fp);
}
}
Run Code Online (Sandbox Code Playgroud)

我的Python代码:

>>> import ctypes
>>> lib = ctypes.cdll.LoadLibrary('/in/vrtime/mahesh/blue/rnd/software/test/test.so')
>>> outfile = "myfirstfile.txt"
>>> lib.openfile(outfile)
File to open for writing = m
Run Code Online (Sandbox Code Playgroud)

我得到的文件名是m,这是char我文件的第一个字符.

如何将整个字符串传递给C端?

rob*_*hek 10

在python3(和你肯定是使用python3作为python2您的代码会幸运的工作)的字符串存储作为wchar_t[]缓冲,所以当你通过"myfirstfile.txt" C函数认为其ARG作为"m\0y\0..."这显然是一个lenght的C字符串.这是表现出来的问题:

In [19]: from ctypes import cdll, c_char_p

In [20]: libc = cdll.LoadLibrary("libc.so.6")

In [21]: puts = libc.puts

In [22]: puts('abc')
a
Run Code Online (Sandbox Code Playgroud)

你应该将一个bytes对象传递给C函数

In [23]: puts(b'abc')
abc
Run Code Online (Sandbox Code Playgroud)

你可以转换strbytes这样的:

puts(my_var.encode())
Run Code Online (Sandbox Code Playgroud)

为避免进一步混淆,您可以指定C函数的参数类型:

In [27]: puts.argtypes = [c_char_p]
Run Code Online (Sandbox Code Playgroud)

现在该函数接受bytes(ctypes将其转换为char*):

In [28]: puts(b'abc')
abc
Run Code Online (Sandbox Code Playgroud)

但不是str:

In [30]: puts('abc')
---------------------------------------------------------------------------
ArgumentError                             Traceback (most recent call last)
<ipython-input-26-aaa5b59630e2> in <module>()
----> 1 puts('abc')

ArgumentError: argument 1: <class 'TypeError'>: wrong type
Run Code Online (Sandbox Code Playgroud)