这是我在这个网站上的第一篇文章。我正在寻求您的帮助,因为我在这个问题上完全迷失了。
我的目标是在我的 Delphi7 项目中包含一个 JSON 解析器,因为在这个版本的 Delphi 中,默认情况下不包含 JSON 处理。
我希望你们对这个问题有一些经验的想法。 我正在等待如何使这项工作的任何建议。 非常感谢您提前提供任何解决方案。
Post Scriptum:是的,也可以选择将此 JSONParser 重写为 Delphi7,但在我的论文中,我正在研究从不同语言调用 DLL,所以我更喜欢这样调用它们,所以这些代码应该更好留在 C 或 C++,因为它更酷。
我尝试了
cdecl
和 stdcall
调用约定,使用不同的字符串组合方式,我什至用 C++ 重写了整个 C 项目,但我仍然遇到 EAccessViolation
错误...
Delphi 中的方法签名 - 第一种方法仅用于证明整个调用 C/C++ 方法概念有效:
function sub(a, b:Integer): Integer; stdcall; external 'calc32.dll' name 'sub'
function create_json1(
device_ids:PWord;
length:Word): PAnsiChar; stdcall; external 'converter32.dll' name 'create_json'
procedure create_json2(
device_ids: PWord;
length: Word;
output: PAnsiChar); stdcall; external 'convertercpp.dll' name 'create_json'
我只会在 C: 中调用的方法签名和实现
extern __declspec(dllexport) char* __stdcall create_json(
unsigned short* device_ids,
unsigned short length){
json device_list_json = json_type(JSON_LIST);
//we need an instance for each JSON-object (each device) to give them different deviceIDs
json* device_objects_json = malloc(sizeof(json) * length);
for (unsigned short i = 0; i < length; i++)
device_objects_json[i] = json_type(JSON_OBJ); //set them as JSON-objects
for (unsigned short i = 0; i < length; i++)
{
json_obj_put_int(&device_objects_json[i], "azonos", device_ids[i]); //add as JSON object {"azonos":16388}
json_list_add(&device_list_json, &device_objects_json[i]); //add to JSON-list [{...},{...},{"azonos":16388}]
}
unsigned short n;
char* output = json_dump(device_list_json, false, (int*)&n);
for (unsigned short i = 0; i < length; i++)
{
json_freeDeep(&device_objects_json[i]);
}
free(device_objects_json);
json_freeDeep(&device_list_json);
return output;
}
C++ 中的方法签名#2:
#include <stdlib.h>
#include <string.h>
#include "json.h"
extern "C" __declspec(dllexport) void __stdcall create_json(
unsigned short* device_ids,
unsigned short length,
char* output){
json OUT = json_type(JSON_LIST);
json* eszkozok = (json*) malloc(sizeof(json)*length);
const char* key = "azonos";
for (int i = 0; i < length; i++)
{
eszkozok[i] = json_type(JSON_OBJ);
}
for (int i = 0; i < length; i++)
{
json_obj_put_int(&eszkozok[i], (char*) key, device_ids[i]);
json_list_add(&OUT, &eszkozok[i]);
}
int n;
strcpy(output, json_dump(OUT, &n));
for (int i = 0; i < length; i++)
{
json_freeDeep(&eszkozok[i]);
}
free(eszkozok);
json_freeDeep(&OUT);
}
调用C方法时出错:
Project C:\Users\Bence\Documents\Pascal\szamologep\szamolo.exe faulted with message: ‘access violation at
0x00632e39: read of address 0x00000000". Process Stopped. Use Step or Run to continue.
调用 C++ 方法时出错:
Project szamolo.exe raised exception class EAccessViolation with message 'Access violation at address OOA60EB7 in
"module 'convertercpp.dll '. Read of address 90A77404', Process stopped, Use Step or Run to continue,"
从 Delphi 调用方法,我只会打印结果:
procedure TForm1.Button1Click(Sender: TObject);
var
device_ids: array of word;
n: word;
i: integer;
output: pansichar;
begin
//showmessage(format('sub implementation in C: %d', [sub(10,5)]));
SetLength(device_ids, 5);
for i := 0 to 4 do
begin
device_ids[i] := (i+1) * 5;
end;
n := length(device_ids);
output := create_json1(pword(device_ids), n);
// create_json2(pword(device_ids), n, output);
// showmessage(format('%s\n', [output]));
end;
结果将是一个简单的 JSON 格式的字符串,其中包含如下对象:
[{"azonos":49156}, {"azonos":16388}, {"azonos":32772}, ...]
在第一个 C 代码中,该函数表现出 undefined behavior 因为它被声明为返回一个
char*
指针,但实际上根本没有 return
任何东西,所以 any 调用者使用返回值将完全没有意义。此外,该函数忽略了调用者传递给 char*
参数的任何 output
指针。因此,无论 json_dump()
返回什么,都不会返回给调用者。
在第二个 C++ 代码中,该函数仍然存在问题,因为
json eszkozok[length];
不是标准的 C++,并且该函数忽略了 char*
参数中调用者的 output
指针。
在您的 Delphi 代码中,您的
create_json1()
声明不匹配 either C/C++ 函数正确,因为它缺少 output
参数,所以 any 在函数内部使用 output
是 undefined behavior .此外,您的 create_json2()
声明仅匹配 C++ 函数,而不匹配 C 函数。