Форум: "Основная";
Текущий архив: 2006.07.23;
Скачать: [xml.tar.bz2];
ВнизПроблема с вызовом DLL на C из программы на Delphi Найти похожие ветки
← →
Valera (2006-06-06 00:17) [0]Суть проблемы.
Имеется программа, написанная на Delphi. Она вызывает DLL, которая написана на C и откомпилирована на Borland C++ Builder 6. Функция, содержащаяся в DLL получает от вызывающей программы в качестве параметров адреса двух двумерных массивов, берет данные из массивов, производит вычисления и пишет результаты вычислений в третий массив, адрес которого также передается в виде параметра. Если результирующий массив - одномерный (вектор), то вызов DLL отрабатывается нормально. Если же сделать результирующий массив двумерным, то при вызове из дельфийской программы DLL выдается ошибка Access Violation ...
Провел следующие эксперименты:
1. Написал вызывающую программу на C и откомпилировал на C++ Builder. Программа на C нормально вызывает ту же самую DLL, на которой спотыкается программа на Delphi.
2. Написал DLL на Delphi. Ее нормально вызывает дельфийская программа, а C-шная программа спотыкается на дельфийской DLL.
Для справки. Соответствие и совместимость типов передаваемых в DLL параметров в Delphi и C соблюдено. Причем проводились эксперименты с разными типами данных. Во всех случаях использовалась динамическая загрузка DLL с помощью функций LoadLibrary и GetProcAddress. Динамическая память в самой DLL не выделяется.
Интересно выяснить чего все-таки я не понимаю в этой жизни. Может быть в Delphi и C по разному организованы двумерные массивы. Хотя входные данные из передаваемых в DLL двумерных массивов читаются правильно (проверялось). Не удается записать данные в двумерный массив. В одномерный получается (см. выше).
Может быть кто-нибудь сталкивался с подобной проблемой ?
← →
atruhin © (2006-06-06 05:57) [1]Не указал тип данных массива. Массивы статические? Размерности соблюдены? Вообщем выкладывай прототип описания функции.
← →
atruhin © (2006-06-06 06:05) [2]Прототипы функций на C++ и delphi
← →
Valera (2006-06-06 15:51) [3]Массивы динамические.
Код процедуры на С:
--------------------------
__declspec(dllexport) int __stdcall MaskWatershedFunction(short WidthImage, short HeightImage,
unsigned char **ArPImageLines,
unsigned char **ArPMaskLines,
unsigned int **ArPWaterLines)
{
int i, j;
for (i=0; i<HeightImage; i++) {
for (j=0; j<WidthImage; j++) {
ArPWaterLines[i][j] = ArPImageLines[i][j] + ArPMaskLines[i][j];
}
}
return 0;
}
А вот основаная часть кода на Delphi:
--------------------------------------
type
TByteMatrix = array of array of byte;
TCardinalMatrix = array of array of Cardinal;
TMaskWatershedFunction = function(WidthImage, HeightImage: Word;
var ArPImageLines: TByteMatrix;
var ArPMaskLines: TByteMatrix;
var ArPWaterLines: TCardinalMatrix): integer; StdCall;
...............
var
WidthImage, HeightImage: Word;
ArPImageLines: TByteMatrix;
ArPMaskLines: TByteMatrix;
ArPWaterLines: TCardinalMatrix;
MaskWatershedFunction: TMaskWatershedFunction;
...............
LibHandle := LoadLibrary("MaskWatershed.dll");
if LibHandle = HINSTANCE_ERROR then
Writeln("Unable to Load DLL");
@MaskWatershedFunction := GetProcAddress(LibHandle, "MaskWatershedFunction");
if not (@MaskWatershedFunction = nil) then
begin
res := MaskWatershedFunction(WidthImage, HeightImage,
ArPImageLines, ArPMaskLines, ArPWaterLines);
end;
← →
Valera (2006-06-06 17:51) [4]Разобрался с проблемой самостоятельно.
Проблема была в моем непонимании принципов передачи open array parameters в Delphi. Проблему решил путем изменения типов передаваемых из Delphi параметров:
const MAXARRAYSIZE = MAXINT;
type
pArPtr0 = ^tArPtr0;
tArPtr0 = array[0..MAXARRAYSIZE div sizeof(pointer)-1] of pointer;
TMaskWatershedFunction = function(WidthImage, HeightImage: Word;
var ArPImageLines: pArPtr0;
var ArPMaskLines: pArPtr0;
var ArPWaterLines: pArPtr0): integer; StdCall;
...............
var
WidthImage, HeightImage: Word;
ArPImageLines: pArPtr0;
ArPMaskLines: pArPtr0;
ArPWaterLines: pArPtr0;
MaskWatershedFunction: TMaskWatershedFunction;
...............
LibHandle := LoadLibrary("MaskWatershed.dll");
if LibHandle = HINSTANCE_ERROR then
Writeln("Unable to Load DLL");
@MaskWatershedFunction := GetProcAddress(LibHandle, "MaskWatershedFunction");
if not (@MaskWatershedFunction = nil) then
begin
res := MaskWatershedFunction(WidthImage, HeightImage,
ArPImageLines, ArPMaskLines, ArPWaterLines);
end;
Код на C в DLL без изменений. В таком виде все работает.
← →
Valera (2006-06-06 17:54) [5]Допустил ошибку в своем последнем сообщении. Вот правильное объявление типа вызываемой из DLL функции:
TMaskWatershedFunction = function(WidthImage, HeightImage: Word;
ArPImageLines: pArPtr0;
ArPMaskLines: pArPtr0;
ArPWaterLines: pArPtr0): integer; StdCall;
Остальное верно.
← →
atruhin © (2006-06-07 06:40) [6]Можно проще:
TMaskWatershedFunction = function(WidthImage, HeightImage: Word;
var ArPImageLines: tArPtr0;
var ArPMaskLines: tArPtr0;
var ArPWaterLines: tArPtr0): integer; StdCall;
То же самое только удобнее.
← →
evvcom © (2006-06-07 08:49) [7]Тогда уж
TMaskWatershedFunction = function(WidthImage, HeightImage: Word;
const ArPImageLines: tArPtr0;
const ArPMaskLines: tArPtr0;
var ArPWaterLines: tArPtr0): integer; StdCall;
идеологически более правильно, хотя результат тот же. :)
← →
atruhin © (2006-06-07 14:59) [8]
> [7] evvcom © (07.06.06 08:49)
> Тогда уж
Красиво. Вроде знал что const указатель передает, но не задумывался о таком использовании. :)
Страницы: 1 вся ветка
Форум: "Основная";
Текущий архив: 2006.07.23;
Скачать: [xml.tar.bz2];
Память: 0.47 MB
Время: 0.014 c