gpt4 book ai didi

json - Delphi PChar 传递给函数时字符串为空

转载 作者:行者123 更新时间:2023-12-03 15:49:55 28 4
gpt4 key购买 nike

如果重要的话,我正在使用Delpi XE6。

我正在编写一个 DLL,它将从 Google 的 Directions API 获取响应,解析生成的 JSON 并确定行程的总距离。

GetJSONString_OrDie 按预期工作。它需要一个 URL 并尝试从 Google 获取响应。如果是,它会返回 Google 返回的 JSON 字符串。

ExtractDistancesFromTrip_OrDie 应该接受一个 JSON 字符串,并解析它以获取旅程每段的总距离,并将这些距离粘贴在 double 组中。

SumTripDistances 接受一个 double 组,并对数组求和,然后返回总计。

奇怪的是,如果我从 DLL 中取出这些函数并将它们放入项目中并像这样调用它们,它就会按预期工作。只有当它们卡在 DLL 中时,才会出现问题。如前所述,GetJSONString_OrDie 按预期工作并返回 JSON 字符串 - 但当单步执行 DLL 的 ExtractDistancesForTrip 时,传递的 PChar 字符串为 ''。这是为什么?

unit Unit1;



interface
uses
IdHTTP,
IdSSLOpenSSL,
System.SysUtils,
System.JSON;

type
arrayOfDouble = array of double;

function GetJSONString_OrDie(url : Pchar) : Pchar;
function ExtractDistancesForTrip_OrDie(JSONstring: Pchar) : arrayOfDouble;
function SumTripDistances(tripDistancesArray: arrayOfDouble) : double;

implementation



{ Attempts to get JSON back from Google's Directions API }
function GetJSONString_OrDie(url : Pchar) : PChar;
var
lHTTP: TIdHTTP;
SSL: TIdSSLIOHandlerSocketOpenSSL;
begin
{Sets up SSL}
SSL := TIdSSLIOHandlerSocketOpenSSL.Create(nil);
{Creates an HTTP request}
lHTTP := TIdHTTP.Create(nil);
{Sets the HTTP request to use SSL}
lHTTP.IOHandler := SSL;
try
{Attempts to get JSON back from Google's Directions API}
Result := PWideChar(lHTTP.Get(url));
finally
{Frees up the HTTP object}
lHTTP.Free;
{Frees up the SSL object}
SSL.Free;
end;
end;

{ Extracts the distances from the JSON string }
function ExtractDistancesForTrip_OrDie(JSONstring: Pchar) : arrayOfDouble;
var
jsonObject: TJSONObject;
jsonArray: TJSONArray;
numberOfLegs: integer;
I: integer;
begin
//raise Exception.Create('ExtractDistancesForTrip_OrDie:array of double has not yet been '+
// 'implemented.');

jsonObject:= nil;
jsonArray:= nil;
try
{ Extract the number of legs in the trip }
jsonObject:= TJSONObject.ParseJSONValue(TEncoding.ASCII.GetBytes(JSONstring), 0) as TJSONObject;
jsonObject:= (jsonObject.Pairs[0].JsonValue as TJSONArray).Items[0] as TJSONObject;
jsonArray:= jsonObject.Pairs[2].JSONValue as TJSONArray;
numberOfLegs:= jsonArray.Count;

{Resize the Resuls arrayOfDouble}
SetLength(Result, numberOfLegs);

{Loop through the json and set the result of the distance of the leg}
{Distance is in km}
for I := 0 to numberOfLegs-1 do
begin
Result[I]:= StrToFloat((((jsonArray.Items[I] as TJSONObject).Pairs[0].JsonValue as TJSONObject).Pairs[1]).JsonValue.Value);
end;


finally
jsonObject.Free;
jsonArray.Free;
end;

end;


function SumTripDistances(tripDistancesArray: arrayOfDouble) : double;
var
I: integer;
begin
//raise Exception.Create('GetDistanceBetweenPoints_OrDie:double has not yet been ' +
// 'implemented.');

Result:= 0;
{Loop through the tripDistancesArray, and add up all the values.}
for I := Low(tripDistancesArray) to High(tripDistancesArray) do
Result := Result + tripDistancesArray[I];


end;

end.

以下是函数的调用方式:

program Project3;

{$APPTYPE CONSOLE}

{$R *.res}

uses
ShareMem,
IdHTTP,
IdSSLOpenSSL,
System.SysUtils,
System.JSON,
System.Classes;

type
arrayOfDouble = array of double;

testRecord = record
testString : string;
testInt : integer;
end;

function GetJSONString_OrDie(url : Pchar) : PWideChar; stdcall; external 'NMBSGoogleMaps.dll';

function ExtractDistancesForTrip_OrDie(JSONstring: pchar) : arrayOfDouble; stdcall; external 'NMBSGoogleMaps.dll';

function SumTripDistances(tripDistancesArray: arrayOfDouble) : double; stdcall; external 'NMBSGoogleMaps.dll';


var
jsonReturnString: string;
jsonReturnString2: Pchar;
doubles: arrayOfDouble;
totalJourney: double;
uri:Pchar;

a : testRecord;
begin
try
uri:= 'https://maps.googleapis.com/maps/api/directions/json?origin=Boston,MA&destination=Concord,MA&waypoints=Charlestown,MA|Lexington,MA&key=GETYOUROWNKEY';


{ TODO -oUser -cConsole Main : Insert code here }
jsonReturnString:= GetJSONString_OrDie(uri); //On step-through, uri is fine.

jsonReturnString2:= stralloc(length(jsonreturnstring)+1);
strpcopy(jsonreturnstring2, jsonreturnstring);
jsonreturnstring2 := 'RANDOMJUNK';

doubles:= ExtractDistancesForTrip_OrDie(jsonReturnString2); //On step-through, jsonReturnString2 is seen as '', rather than 'RANDOMJUNK'
totalJourney:= SumTripDistances(doubles);
WriteLn('The total journey was: ');
WriteLn(totalJourney);

except
on E: Exception do
Writeln(E.ClassName, ': ', E.Message);
end;
readln;
end.

当调用第一个函数GetJSONString_OrDie时,uri被传入,并且在查看或打印时是正确的。但是,在创建随机字符串并将其传递到 ExtractDistancesForTrip_OrDie 后,该函数只能看到 ''。如果我要更改 ExtractDistancesForTrip_OrDie 以接受整数、记录或任何内容 - 它会看到垃圾或随机数据。我是否通过引用或值传递并不重要。

最佳答案

您的调用约定不匹配。您的函数使用 register 调用约定,但您可以像 stdcall 一样导入它们。这就是为什么您传递的参数没有到达的原因。

在实现函数和导入函数时都使用stdcall

GetJSONString_OrDie中,您将返回一个指向局部变量缓冲区的指针。一旦函数返回,该局部变量就会被销毁,并且指针无效。您需要找到一种不同的方法来将字符串数据传递出该函数。

返回一个字符串通常就可以了。但由于该函数是从 DLL 导出的,因此无法工作。您需要一个调用者分配的缓冲区,或者一个在共享堆上分配的缓冲区。

最后,动态数组不是有效的互操作类型。您不应该跨模块边界传递它们。

关于json - Delphi PChar 传递给函数时字符串为空,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30891803/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com