从C ++ DLL

时间:2017-12-06 02:25:12

标签: c++ visual-c++ dll delphi-5

我试图使用从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传递地址/指针到dll的方法,但是他们并没有改变任何东西。

现在,返回值正确发送,但记录的字段(即值)保持不变。

我需要对Delphi或C ++进行哪些更改才能捕获传递记录中的更改?我很高兴与C ++广泛合作,但我更喜欢将Delphi的变化保持在最低限度,因为这是我不想破解的旧软件。

1 个答案:

答案 0 :(得分:1)

function foo(CVars : dll_btvar):integer; external 'example.dll';

问题从Delphi代码开始。记录按值传递。也就是说,调用者的记录变量被复制到一个新变量,然后传递给该函数。这意味着调用者不会看到被调用者对该记录副本的修改。因此,您必须将参数作为var参数传递:

function foo(var CVars : dll_btvar):integer; external 'example.dll';

下一个问题是调用约定。您必须为双方使用相同的调用约定。您的代码使用Delphi端的默认register约定,非Borland / Embarcadero工具不支持该约定。请改用stdcallcdecl。我们选择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;
}
  

在C ++ Builder 5中使用相同的代码确实有效。

不是没有,因为你问题中的Delphi代码无法修改来电者的记录。

相关问题