I think you mixed dynamic array and open array. Which are worded the same but in different contexts.
http://rvelthuis.de/articles/articles-openarr.html
Try this:
type TPAnsiCharDynArray = array of PAnsiChar;
function callPluginFunction(plugin, method: PAnsiChar;
synchronous :boolean; param: array of PAnsiChar;
out returnParam: TPAnsiCharDynAttay): integer;
Also this line is problematic:
for i:=0 to 6 do
p[i]:= param[i];
Either you know for sure that your arrays are ALWAYS 0..6 - then there is no point in using dynamic arrays.
type TDLLVectorIndex = 0..6;
TDLLPCharArray = array [TDLLVectorIndex] of PAnsiChar;
function callPluginFunction(const plugin, method: PAnsiChar;
synchronous :boolean;
const param: TDLLPCharArray;
out returnParam: TDLLPCharArray): integer;
Don't forget argument modifiers const/var/out to document your call contract AND to make values passed by-reference rather than cloned and passed as-value
Or you don't know exact dimensions - then you should not assume 6 magic number and iterate to the real size of array passed in.
for i:=0 to High(param) do
p[i]:= param[i];
However this does not seems to be your case, but it was very striking that you explicitly declare parameter "god-only-knows-what-length-array" and then use it with hardcoded magic constant.
Again, if you make PAscal bridge, then using PAscal string is better than using C char pointers.
function callPluginFunction(const plugin, method: AnsiString;
synchronous :boolean;
.....
Track down what is C bool type. Is it really single-byte boolean ? Or is it some Windows bools, that can take 1,2 or even 4 bytes ? it also sometimes has slight binary incompatibilities of what is true actually, +1 or -1.
But without that bool uncertainty, you fn declaration after applying argument qualifiers would better look like.
type fn_dpstate_callPluginFunction =
function(const plugin, method: PAnsiChar; synchronous: boolean;
const p0, p1, p2, p3, p4, p5, p6: PAnsiChar;
var o0, o1, o2, o3, o4, o5, o7: PAnsiChar): integer; cdecl;
var dpstate_callPluginFunction: fn_dpstate_callPluginFunction;
In C++ passing parameters by-ref is not popular, and in C it maybe does not exist. But in average Pascal code passing parameters by-ref considered to be more usual and more safe, than passing pointers.
This comes to bridge re-coding:
type TDLLVectorIndex = 0..6;
TDLLPCharArray = array [TDLLVectorIndex] of PAnsiChar;
function PConnect.callPluginFunction(const plugin, method: AnsiString;
synchronous :boolean;
const p: TDLLPCharArray;
out o: TDLLPCharArray): integer;
var Error: integer;
begin
Error :=
dpstate_callPluginFunction( PAnsiChar(plugin), PAnsiChar(method), synchronous,
p[0], p[1], p[2], p[3], p[4], p[5], p[6],
@o[0], @o[1], @o[2], @o[3], @o[4], @o[5], @o[6]);
Result := Error + 10;
// or something like that - you did had the reason
// to declare the var and declare function return type afterall
end;
procedure TForm1.btn_pluginFunctionClick(Sender: TObject);
var param, returnParam: TDLLPCharArray;
begin
FillChar(param, 0, SizeOf(TDLLPCharArray)); // maybe redundant, but to be on safe side
param[0]:= 'Param1';
param[1]:= 'Param2';
connector.callPluginFunction('dpserverplugin', 'showconfigdialog', true, param, returnParam);
....
PS. Last but not least, does your connector have any real member variables inside ? i mean non-static ones, those that be different among several connector instances ? If not you'd probably make callPluginFunction a class function and not create instances of connector class at all.
param[0]:= 'Param1';
param[1]:= 'Param2';
PConnect.callPluginFunction('dpserverplugin', 'showconfigdialog', true, param, returnParam);
PPS. David is very right about contract. Especially about "Who allocates memory?" Even if the DLL just returns string constants, there is a neat gotcha: Load DLL, get pointer to string, Unload DLL, try to use the pointer - access violation. So while the bridge above is what i believe the correct interface translation, it is not necessarily working in larger picture, due to the issues pointed by David.
PPPS. array datatype declaration may seem edundant, but it overcomes what i consider a stupid limitation of Delphi novadays: why two aliases to "array of string" treated differently?
PPPPS. using out parameters is controversial. For example David thinks that since Delphi does not actually implements them for most of data types, one should almost always use var parameters instead. Personally i think that using out parameters is good for documenting your contract and is good for compatibility with FPC and other compilers.
@o[0], that's actually a pointer toPPAnsiChar. But the function expectsPPAnsiChar. So that's a mismatch. But we still don't know what the interface contract is. Describe the rules for thechar**parameters. In my view you need to simplify the interface considerably for us to help. Try a version which uses just a singlechar**parameter and see if you can make it work.