Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2006.07.23;
Скачать: CL | DM;

Вниз

Проблема с вызовом 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;
Скачать: CL | DM;

Наверх




Память: 0.5 MB
Время: 0.028 c
15-1151164272
DillerXX
2006-06-24 19:51
2006.07.23
forgot-me-not


2-1151750298
KaLLeKa
2006-07-01 14:38
2006.07.23
Как получить имя файла БЕЗ расширения?


11-1130734441
Reset
2005-10-31 07:54
2006.07.23
Убрать PopupMenu, если оно уже "вывалилось"?


2-1151662799
D@Nger
2006-06-30 14:19
2006.07.23
DBGrid и отключение редактирование колонки.


15-1150177750
Ega23
2006-06-13 09:49
2006.07.23
С Днём рождения! 10 июня