Tha*_*all 12 c python ctypes language-binding
我是一名Python资深人士,但在C中没有涉足太多.在互联网上找不到任何适用于我的东西半天之后,我想我会问这里并得到我需要的帮助.
我想要做的是编写一个简单的C函数,它接受一个字符串并返回一个不同的字符串.我打算用几种语言(Java,Obj-C,Python等)绑定这个函数,所以我认为它必须是纯C?
这是我到目前为止所拥有的.注意我在尝试在Python中检索值时遇到了段错误.
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
const char* hello(char* name) {
static char greeting[100] = "Hello, ";
strcat(greeting, name);
strcat(greeting, "!\n");
printf("%s\n", greeting);
return greeting;
}
Run Code Online (Sandbox Code Playgroud)
import ctypes
hello = ctypes.cdll.LoadLibrary('./hello.so')
name = "Frank"
c_name = ctypes.c_char_p(name)
foo = hello.hello(c_name)
print c_name.value # this comes back fine
print ctypes.c_char_p(foo).value # segfault
Run Code Online (Sandbox Code Playgroud)
我已经读过,segfault是由C释放最初为返回的字符串分配的内存引起的.也许我只是在咆哮错误的树?
什么是实现我想要的正确方法?
tde*_*ney 16
您的问题是在堆栈上分配了问候语,但是当函数返回时,堆栈被销毁.您可以动态分配内存:
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
const char* hello(char* name) {
char* greeting = malloc(100);
snprintf("Hello, %s!\n", 100, name)
printf("%s\n", greeting);
return greeting;
}
Run Code Online (Sandbox Code Playgroud)
但这只是战斗的一部分,因为现在你有内存泄漏.你可以用另一个ctypes调用free()来插入它.
...或者更好的方法是阅读官方C绑定到python(python 2.x在http://docs.python.org/2/c-api/和python 3.x在http:/ /docs.python.org/3/c-api/).让你的C函数创建一个python字符串对象并将其交回.它将被python自动收集垃圾.既然你正在编写C面,你就不必玩ctypes游戏了.
...编辑..
我没有编译和测试,但我认为这个.py会起作用:
import ctypes
# define the interface
hello = ctypes.cdll.LoadLibrary('./hello.so')
# find lib on linux or windows
libc = ctypes.CDLL(ctypes.util.find_library('c'))
# declare the functions we use
hello.hello.argtypes = (ctypes.c_char_p,)
hello.hello.restype = ctypes.c_char_p
libc.free.argtypes = (ctypes.c_void_p,)
# wrap hello to make sure the free is done
def hello(name):
_result = hello.hello(name)
result = _result.value
libc.free(_result)
return result
# do the deed
print hello("Frank")
Run Code Online (Sandbox Code Playgroud)
小智 6
n hello.c你返回一个本地数组.您必须返回一个指向数组的指针,该数组必须使用malloc动态声明.
char* hello(char* name)
{
char hello[] = "Hello ";
char excla[] = "!\n";
char *greeting = malloc ( sizeof(char) * ( strlen(name) + strlen(hello) + strlen(excla) + 1 ) );
if( greeting == NULL) exit(1);
strcpy( greeting , hello);
strcat(greeting, name);
strcat(greeting, excla);
return greeting;
}
Run Code Online (Sandbox Code Playgroud)
我今天遇到了同样的问题,发现您必须通过设置方法来覆盖默认返回类型( int
) 。restype
请参阅此处ctype 文档中的返回类型。
import ctypes
hello = ctypes.cdll.LoadLibrary('./hello.so')
name = "Frank"
c_name = ctypes.c_char_p(name)
hello.hello.restype = ctypes.c_char_p # override the default return type (int)
foo = hello.hello(c_name)
print c_name.value
print ctypes.c_char_p(foo).value
Run Code Online (Sandbox Code Playgroud)