Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Основная";
Текущий архив: 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
2-1151306326
XTD
2006-06-26 11:18
2006.07.23
Автоответчик (модем+комп)


2-1151117256
learner
2006-06-24 06:47
2006.07.23
Сообщение в нить, созданной CreateThread


15-1151147411
mio
2006-06-24 15:10
2006.07.23
Закрытие программы.


3-1147876311
S@shka
2006-05-17 18:31
2006.07.23
Сбросить данные из таблицы в файл.


2-1151850216
Yaro
2006-07-02 18:23
2006.07.23
вызвать property класса-родителя





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский