我已经在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()那样立即返回。