3

我目前正在使用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');

我怎样才能解决这个问题?有没有办法调试此类错误?

4

1 回答 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]

后者至少是类型安全的。


我注意到您声明AAAandBBB是 type PChar。当然应该是这样PAnsiChar


我不确定您是否已正确准备所有其他参数。我不熟悉这个特定的 API 调用。不过,可以肯定的是,我上面描述的是要解决的第一个也是最重要的问题。

我确实想知道调用者如何释放返回给您的字符串?我想你应该这样做。

于 2014-04-19T14:12:06.333 回答