从 C++ DLL 编辑 Delphi 条记录
Edit Delphi record from C++ DLL
我正在尝试使用从 Delphi 5 程序调用的 Visual C++ 创建 DLL。 Delphi程序传入一条记录,然后在DLL中编辑,Delphi程序使用结果。
例如,Delphi 代码类似于以下内容:
Type dll_btvar = record
age : smallint;
name : array[0..11] of char;
value : Double;
end;
// Import the function from the dll
function foo(CVars : dll_btvar):integer; external 'example.dll';
// Call the dll
function callFoo(var passedVar:dll_btvar):integer;
begin
result := foo(passedVar);
// Use passedVar.value
end;
C++ 代码示例:
在example.h中:
#pragma once
#include "dllVar.h"
extern "C" {
__declspec(dllexport) int foo(DLL_Var var);
}
在example.cpp中:
#include "example.h"
int foo(DLL_Var var){
var.value = var.age + var.name[0];
return 0;
}
在dllVar.h中:
#pragma once
#pragma pack(8)
extern "C" {
struct DLL_Var {
short age;
char name[12];
double value;
}
}
我使用 #pragma pack(8)
,因为该值给出了正确的对齐方式,以便在 DLL 中正确读取传递的记录。
在示例代码中,当传递年龄和姓名时,我希望值由 DLL 设置,然后可以在 Delphi 程序中恢复。结果将是某种错误代码。
在 C++ Builder 5 中使用相同的代码确实有效,但它当然已经过时并且我没有移动我的 DLL 中的所有代码(我也不想),只有你在这里看到的最少代码。
我测试了几种让 Delphi 将 address/pointer 传递给 dll 的方法,但是它们并没有改变任何东西。
现在,return 值已正确发送,但记录的字段(即值)保持不变。
我需要对 Delphi 或 C++ 进行哪些更改才能捕获传递记录中的更改?我很高兴广泛使用 C++,但我更愿意将 Delphi 更改保持在最低限度,因为这是我不想破坏的旧软件。
function foo(CVars : dll_btvar):integer; external 'example.dll';
问题从这里开始,在 Delphi 代码中。记录按值传递。也就是说,调用者的记录变量被复制到一个新变量,然后传递给函数。这意味着调用者看不到被调用者对此记录副本所做的修改。因此,您必须将参数作为 var
参数传递:
function foo(var CVars : dll_btvar):integer; external 'example.dll';
下一个问题是调用约定。双方必须使用相同的调用约定。您的代码在 Delphi 端使用默认的 register
约定,non-Borland/Embarcadero 工具不支持该约定。请改用 stdcall
或 cdecl
。让我们选择 cdecl
,这是大多数 C++ 工具的默认值:
function foo(var CVars : dll_btvar):integer; cdecl; external 'example.dll';
要使 C++ 代码匹配,通过引用传递参数:
__declspec(dllexport) int __cdecl foo(DLL_Var &var);
或显式使用指针:
__declspec(dllexport) int __cdecl foo(DLL_Var *var);
后一个选项中,由于使用了指针,需要更改实现:
int foo(DLL_Var *var){
var->value = var->age + var->name[0];
return 0;
}
Using identical code in C++ Builder 5 did work.
不对,因为你问题中的Delphi代码无法修改来电记录。
我正在尝试使用从 Delphi 5 程序调用的 Visual C++ 创建 DLL。 Delphi程序传入一条记录,然后在DLL中编辑,Delphi程序使用结果。
例如,Delphi 代码类似于以下内容:
Type dll_btvar = record
age : smallint;
name : array[0..11] of char;
value : Double;
end;
// Import the function from the dll
function foo(CVars : dll_btvar):integer; external 'example.dll';
// Call the dll
function callFoo(var passedVar:dll_btvar):integer;
begin
result := foo(passedVar);
// Use passedVar.value
end;
C++ 代码示例:
在example.h中:
#pragma once
#include "dllVar.h"
extern "C" {
__declspec(dllexport) int foo(DLL_Var var);
}
在example.cpp中:
#include "example.h"
int foo(DLL_Var var){
var.value = var.age + var.name[0];
return 0;
}
在dllVar.h中:
#pragma once
#pragma pack(8)
extern "C" {
struct DLL_Var {
short age;
char name[12];
double value;
}
}
我使用 #pragma pack(8)
,因为该值给出了正确的对齐方式,以便在 DLL 中正确读取传递的记录。
在示例代码中,当传递年龄和姓名时,我希望值由 DLL 设置,然后可以在 Delphi 程序中恢复。结果将是某种错误代码。
在 C++ Builder 5 中使用相同的代码确实有效,但它当然已经过时并且我没有移动我的 DLL 中的所有代码(我也不想),只有你在这里看到的最少代码。
我测试了几种让 Delphi 将 address/pointer 传递给 dll 的方法,但是它们并没有改变任何东西。
现在,return 值已正确发送,但记录的字段(即值)保持不变。
我需要对 Delphi 或 C++ 进行哪些更改才能捕获传递记录中的更改?我很高兴广泛使用 C++,但我更愿意将 Delphi 更改保持在最低限度,因为这是我不想破坏的旧软件。
function foo(CVars : dll_btvar):integer; external 'example.dll';
问题从这里开始,在 Delphi 代码中。记录按值传递。也就是说,调用者的记录变量被复制到一个新变量,然后传递给函数。这意味着调用者看不到被调用者对此记录副本所做的修改。因此,您必须将参数作为 var
参数传递:
function foo(var CVars : dll_btvar):integer; external 'example.dll';
下一个问题是调用约定。双方必须使用相同的调用约定。您的代码在 Delphi 端使用默认的 register
约定,non-Borland/Embarcadero 工具不支持该约定。请改用 stdcall
或 cdecl
。让我们选择 cdecl
,这是大多数 C++ 工具的默认值:
function foo(var CVars : dll_btvar):integer; cdecl; external 'example.dll';
要使 C++ 代码匹配,通过引用传递参数:
__declspec(dllexport) int __cdecl foo(DLL_Var &var);
或显式使用指针:
__declspec(dllexport) int __cdecl foo(DLL_Var *var);
后一个选项中,由于使用了指针,需要更改实现:
int foo(DLL_Var *var){
var->value = var->age + var->name[0];
return 0;
}
Using identical code in C++ Builder 5 did work.
不对,因为你问题中的Delphi代码无法修改来电记录。