визуальное редактирование Delphi-записи из C ++ DLL

Я пытаюсь создать DLL с помощью Visual C ++, который вызывается из программы Delphi 5. Программа 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 ++:

В примере .h:

#pragma once
#include "dllVar.h"extern "C" {
__declspec(dllexport) int foo(DLL_Var var);
}

В примере .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

Решение

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

Проблема начинается здесь, в коде Delphi. Запись передается по значению. То есть переменная записи вызывающей стороны копируется в новую переменную, которая затем передается функции. Это означает, что изменения, вызываемые вызываемым пользователем в эту копию записи, не видны вызывающим абонентом. Поэтому вы должны передать параметр как var параметр:

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

Следующая проблема — соглашение о вызовах. Вы должны использовать одно и то же соглашение о вызовах для обеих сторон. Ваш код использует по умолчанию register соглашение на стороне Delphi, которое не поддерживается инструментами не 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;
}

Использование идентичного кода в C ++ Builder 5 сработало.

Нет, это не так, потому что код Delphi в вашем вопросе не может изменить запись звонящего.

1

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]