如何在Delphi中使用C API函数PyArg_ParseTupleAndKeywords?
我现在正在用 python4delphi 写一个Python模块。我想使用标准的C语言API函数 PyArg_ParseTupleAndKeywords。
从文档中可以看到,这个函数的用法是这样的:
int PyArg_ParseTupleAndKeywords(PyObject *args, PyObject *kw, const char *format,
char *keywords[], ...)
现在这个函数在python4delphi中没有封装,所以我自己添加了它:
PyArg_ParseTupleAndKeywords: function (args, kw: PPyObject; format: PAnsiChar;
keywords: array of PAnsiChar {;...}): Integer; cdecl varargs;
....
PyArg_ParseTupleAndKeywords := Import('PyArg_ParseTupleAndKeywords');
我遇到的问题是,当我尝试像下面这个代码片段那样使用它时,出现了访问违规的错误:
function PyScript_MyFunction(pself, args, keywds : PPyObject) : PPyObject; cdecl;
var
AAA, BBB : PChar;
kwlist : array[0..2] of PAnsiChar;
begin
kwlist[0] := 'AAA';
kwlist[1] := 'BBB';
kwlist[2] := nil;
BBB := 'BBB';
with GetPythonEngine do
begin
if (PyErr_Occurred() = nil) and (PyArg_ParseTupleAndKeywords(args, keywds,
's|s:Script_MyFunction', kwlist, @AAA, @BBB) <> 0) then
begin
Result := VariantAsPyObject(MyFunction(AAA, BBB));
end
else
Result := nil;
end;
end;
//Module is my Python module I am working with
Module.AddMethodWithKeywords('Wrapped', @PyScript_MyFunction, 'no doc');
我该如何解决这个问题?有没有办法调试这种错误?
1 个回答
4
你对keywords
参数的理解不太正确。你用了Delphi的开放数组。Delphi的开放数组会传递两个东西,一个是数组最后一个元素的索引,另一个是数组第一个元素的指针。其实,Delphi的开放数组根本不应该用来进行跨语言调用。
你需要这样声明这个参数:
keywords: PPAnsiChar
这实际上是一个指向PAnsiChar
的指针。
调用这个函数时应该这样:
PyArg_ParseTupleAndKeywords(..., @kwlist[0], ...)
我个人建议使用动态数组来准备你的参数:
var
kwlist: TArray<PAnsiChar>;
初始化时可以这样做:
kwlist := TArray<PAnsiChar>.Create('AAA', 'BBB', nil);
然后这样传递它:
PPAnsiChar(kwlist)
或者如果你更喜欢这样:
@kwlist[0]
后者至少是类型安全的。
我注意到你把AAA
和BBB
声明为PChar
类型。其实应该是PAnsiChar
。
我不太确定你是否正确准备了其他所有参数。我对这个特定的API调用不太熟悉。不过,以上我提到的内容是你需要首先解决的最重要的问题。
我还想知道,作为调用者,你是如何处理返回给你的字符串的?我想你应该负责处理这些字符串。