如何在Delphi中使用C API函数PyArg_ParseTupleAndKeywords?

时间:2014-04-19 13:56:31

标签: python c delphi python4delphi

我目前正在使用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 个答案:

答案 0 :(得分:4)

keywords参数的翻译不正确。您使用过Delphi开放式阵列。 Delphi open数组导致传递两件事,数组中最后一项的索引,以及指向数组第一个元素的指针。 Delphi开放数组绝不会用于互操作。

您需要声明该参数:

keywords: PPAnsiChar

这是指向PAnsiChar的指针。

像这样调用函数:

PyArg_ParseTupleAndKeywords(..., @kwlist[0], ...) 

就个人而言,我会使用动态数组来准备你的参数:

var
  kwlist: TArray<PAnsiChar>;

初始化如下:

kwlist := TArray<PAnsiChar>.Create('AAA', 'BBB', nil);

并按照这样传递:

PPAnsiChar(kwlist)

或者喜欢这个,如果您愿意:

@kwlist[0]

后者至少是类型安全的。


我注意到您声明AAABBB属于PChar类型。当然应该是PAnsiChar


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

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