Reputation: 1540
I am currently writing a Python module using python4delphi. I would like to use the standard C API Function PyArg_ParseTupleAndKeywords.
As you can see from the documentation the signature is so:
int PyArg_ParseTupleAndKeywords(PyObject *args, PyObject *kw, const char *format,
char *keywords[], ...)
Now this function is not wrapped in python4delphi so I've added it by myself:
PyArg_ParseTupleAndKeywords: function (args, kw: PPyObject; format: PAnsiChar;
keywords: array of PAnsiChar {;...}): Integer; cdecl varargs;
....
PyArg_ParseTupleAndKeywords := Import('PyArg_ParseTupleAndKeywords');
The problem I have is that I am getting an access violation error when I try to use it in way similar to this snippet:
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');
How can I fix this? Is there a way to debug such kind of errors?
Upvotes: 3
Views: 550
Reputation: 613342
Your translation of the keywords
parameter is incorrect. You've used a Delphi open array. A Delphi open array results in two things being passed, the index of the final item in the array, and the pointer to the first element of the array. Delphi open arrays are simply never to be used for interop.
You need to declare that parameter like so:
keywords: PPAnsiChar
That is a pointer to PAnsiChar
.
Call the function like this:
PyArg_ParseTupleAndKeywords(..., @kwlist[0], ...)
Personally I would use a dynamic array to prepare your parameter:
var
kwlist: TArray<PAnsiChar>;
Initialise it like this:
kwlist := TArray<PAnsiChar>.Create('AAA', 'BBB', nil);
And pass it like this:
PPAnsiChar(kwlist)
or like this if you prefer:
@kwlist[0]
The latter is typesafe at least.
I note that you declared AAA
and BBB
to be of type PChar
. Surely that should be PAnsiChar
.
I'm far from sure that you've prepared all the other parameters correctly. I'm not familiar with this particular API call. For sure though, what I describe above is the first and most important problem to tackle.
I do wonder how you the caller are expected to deallocate the strings that are returned to you? I presume that you are expected to do that.
Upvotes: 4