有如下一个用 C 写的扩展模块: mytest. 我的问题是:在 PY 中如何给实参呢?
#include <stdio.h>
#include "Python.h"
char* gets_s(char s[],int n) {
int c;
char *cs;
if((cs=s)==NULL) return NULL;
while(--n>0 && (c=getc(stdin))!=EOF && c!='\n')
*cs++=c;
*cs='\0';
return (c==EOF && cs==s) ||(c=='\n' && cs==s)? NULL : s ;
}
static PyObject* mytest_get(PyObject *self, PyObject *args) {
int n;
char * s=NULL;
if(!PyArg_ParseTuple(args, "si", &s, &n))
return NULL;
return (PyObject*)Py_BuildValue("s", gets_s(s,n));
}
#python 中:
import mytest
from ctypes import *
arr = (c_byte * 10)() # c_char*10
print('input: ')
mytest.gets_s(arr,10)# TypeError: must be str, not c_byte_Array_10
//另外在C中如何写这样的导出函数:
struct demo {
char name[10];
int age;
};
void GetString(struct demo *p) {
strcpy(p->name, "My Test");
p->age = 1;
}
static PyObject* wrap_GetString(PyObject *self, PyObject *args) {
struct demo* s;
if(!PyArg_ParseTuple(args, "?", &s)) //这里的类型如何写?
1
wangxn 2017-02-26 01:37:22 +08:00 via Android
这么复杂的东西怎么能三言两语说清楚,楼主去啃啃文档中扩展开发相关的内容吧。
|
2
MetaGen 2017-02-26 20:23:41 +08:00
用 cffi 多简单,为啥要用 CPython 的接口
|
3
Daetalus 2017-03-01 18:11:46 +08:00 1
第一个问题,从原理上来说, Python 中字符串是不可变的。而根据 C 模块的代码,"si"表示接收的是字符串,而 Python 中字符串是不可变的,因此不能像 C 语言中那样先创建一个长度为 10 的空字符串,然后传入函数,在函数中修改其中的内容(这只是原理,你的代码中并没有修改)。因此要么用字符列表,要么就改变思维方式。
又看了下你的代码,我觉得可以直接使用 input()函数,获取字符串对象,然后传到 C 层面中并解析给一个 const char*对象。如果仅仅想实验一些 C API 的功能,还是要注意 Python 和 C 在思维上的差别。 PS :你的 C 代码写的不错啊!看上去是有经验的。 第二个问题, Python 中所有都是对象,这个对象在 C 层面指的是 PyObject ,所以从 Python 层面传来的参数不能直接通过`if(!PyArg_ParseTuple(args, "?", &s))`解析给 C 层面的纯 struct 对象。 有几种解决方案: 1 、弄个中间的结构体,其中含有 PyObject_HEAD : typedef struct { PyObject_HEAD xxx; } PyXxxxObject; 然后将这个对象转成 demo 对象。要么直接把 demo 定义成 PyObject 对象。之后就是传递 O 对象了。 2 、使用 struct 模块,位于标准库中,不用担心移植性。具体参考相关文档。 3 、利用 PyDictObject 和 PyListObject 进行一些较为复杂的模拟。应该是可行的,但我没想好细节。就不给出代码了。 对了,强烈、强烈建议不要混用 ctype 和 Python C API 。 |