如何将一个大字符串从delphi dll传递给php扩展

时间:2018-03-23 18:38:02

标签: php delphi

我已经在Visual Studio Express中为PHP 7(NTS for Windows 7)编写了一个php扩展(全部为64位)。我用它来访问用C ++编写的第三方.dll,它运行正常。

现在我希望它能够访问我在Delphi XE6中编写的.dll。 .dll中的函数将字符串作为PAnsiChar返回。它实际上是一个base64编码的jpeg图像,因此可能非常大。我选择将其作为base64编码的字符串发送,因为我看不到将扩展中的图像或字节数组传递回PHP的任何方法。

我的Delphi代码是:

function dem_get_map_img(imgdata: PAnsiChar): int32; stdcall;
var
  base64str: ansistring;
begin
   base64str := 'test return value';   // the actual image data will go here
   imgdata := PAnsiChar(base64str);
   Result := 27;                       // some meaningful value will be used later 
end;

我的PHP扩展代码是:

PHP_FUNCTION(dem_get_map_img)
{
    hGetProcIDDelphiDLL = LoadLibrary(_T("delphiDLL.dll"));
    if (!hGetProcIDDelphiDLL) RETURN_STRING("dll not loaded");

    int rc;
    char imgdata[AS_MAXCH];

    if (ZEND_NUM_ARGS() != 0) RETURN_STRING("wrong param count loaded");

    FARPROC lpfnGetProcessID = GetProcAddress(HMODULE(hGetProcIDDelphiDLL), "dem_get_map_img");
    if (!lpfnGetProcessID) RETURN_STRING("function not found");

    typedef int32(__stdcall * pICFUNC)(char *imgdata);

    pICFUNC dem_get_map_img;
    dem_get_map_img = pICFUNC(lpfnGetProcessID);

    rc = dem_get_map_img(imgdata);

    FreeLibrary(hGetProcIDDelphiDLL);

    array_init(return_value);
    add_assoc_long(return_value, "retflag", rc);
    add_assoc_string(return_value, "imgdata", imgdata);
}

我的PHP代码是:

$outval = dem_get_map_img();
var_dump($outval);

给了我:

array(2) {
  ["retflag"]=>
  int(27)
  ["imgdata"]=>
  string(4) "�$�"
}

不是我所希望的。

首先,我注意到AS_MAXCH显然只允许我255个字符,这将是一个问题(帮助?)但到目前为止不应该是问题。

我已经阅读了各种类似的问题,并假设释放的内存可能是问题所在,但到目前为止,我一直无法弄清楚该怎么办。

我见过人们推荐使用CoTaskMemAlloc,但是我如何在Delphi中做到这一点?

我真正需要做的是将我的Delphi dll中的Jpeg图像传递给PHP扩展并传递到我的PHP代码中,所以如果有更好的方法,那么我愿意接受建议。我对C / C ++和PHP扩展的了解非常有限(你已经知道不是你了)。

任何帮助都将不胜感激。

更新:

你有多愚蠢(我可以得到)吗?

我刚刚意识到我在Delphi函数中做错了什么。

修订Delphi功能:

function dem_get_map_img(imgdata: PAnsiChar): int32; stdcall;
var
  base64str: ansistring;
begin
   base64str:= 'test return value';
   StrPCopy(imgdata, base64str);
   Result := 27;
end;

填写PAnsiChar,不要创建新的!

我仍然很好奇是否有人有更好的建议将图像或大块数据传递给PHP。

更新2:

嗯,非常感谢David Heffernan指出我正确的方向,我想我已经拥有它了。

我拆分Delphi函数,这样我现在有一个函数可以准备字符串并返回大小,

Result := length(MapImage) * sizeof(ansichar) + 1;

和另一个像以前一样返回实际字符​​串数据。

所以现在我调用第一个函数来准备数据,并在调用第二个函数之前使用返回的数据大小来分配内存。

我的新扩展程序代码为:

PHP_FUNCTION(dem_get_map_img)
{
    hGetProcIDDelphiDLL = LoadLibrary(_T("delphiDLL.dll"));
    if (!hGetProcIDDelphiDLL) RETURN_STRING("not loaded");

    long rc, imgsize;
    char * imgdata;

    if (ZEND_NUM_ARGS() != 0) RETURN_STRING("wrong param count loaded");

    FARPROC lpfnGetPrepID = GetProcAddress(HMODULE(hGetProcIDDelphiDLL), "dem_prepare_map_img");
    if (!lpfnGetPrepID) RETURN_STRING("prepare function not found");

    typedef int32(__stdcall * pICprep)(long wid, long hei);
    pICprep dem_prepare_map_img;
    dem_prepare_map_img = pICprep(lpfnGetPrepID);

    imgsize = dem_prepare_map_img(900, 450);

    imgdata = (char*)malloc(imgsize);

    FARPROC lpfnGetGetID = GetProcAddress(HMODULE(hGetProcIDDelphiDLL), "dem_get_map_img");
    if (!lpfnGetGetID) RETURN_STRING("get function not found");

    typedef int32(__stdcall * pICget)(char *imgdata);
    pICget dem_get_map_img;
    dem_get_map_img = pICget(lpfnGetGetID);

    rc = dem_get_map_img(imgdata);

    FreeLibrary(hGetProcIDDelphiDLL);

    array_init(return_value);
    add_assoc_long(return_value, "retflag", rc);
    add_assoc_long(return_value, "imgsize", imgsize);
    add_assoc_string(return_value, "imgdata", imgdata);

    free(imgdata);
}

我的网页上有一张漂亮的地图!

我现在唯一真正关心的是 free(imgdata)正在接触。据我所知,扩展函数只返回函数末尾的 return_value ,而不是像 RETURN_STRING()那样立即返回。

0 个答案:

没有答案