Извикване от Delphi към DLL, написан на C
Здравейте! Имам въпрос относно работата с типа puchar. Такава ситуация: има dll файл, написан на C++Builder. Функцията се експортира от dll както следва
extern "C" bool __declspec(dllexport) func1(неподписан char *вход, неподписан char *изход);
В проекта Delphi импортираме тази функция:
func1(вход: указател; изход: указател): bool; cdecl; външно "my.dll" име "_func1";
Работим с импортираната функция func1:
procedure TForm1.Button1Click(Sender: TObject); var i :integer; s : низ; a: масив [0..30000] от char; b: ^uchar;
a2: масив [0..60000] от uchar; b2: ^uchar; begin StrCopy(a, pchar(Memo1.Text));
for I := 0 to Length(Memo1.Text) do s := s + chr(a2[i]); Memo2.Text := s; end;
Проблемъте, че func1 вижда само първия (нулев) знак от масива "a" и е необходимо целият масив да бъде достъпен за dll.
Тук във входния параметър на dll ShowMessage((char *)input);
Моля, обяснете как правилно да подадете указател към uchar от Delphi към dll. Благодаря много предварително!
> func1(PChar(a), PChar(a2));Това ли ви трябва?
Пробвах го, ефектът е същият като преди. Предава се само нулевият знак, бих искал целият масив да бъде достъпен за dll.
a: масив [0..30000] от char; b: PChar абсолютно a;
a2: масив [0..60000] от uchar; b2: PChar абсолютно a2;
> Предава се само нулевия знакСлучайно първият знак не е #00?
> > Предава се само нулев знак. Първият символ не е #00 или > случайно?не. този в Memo1 на първа позиция се предава.
тогава Delphi се кълне за достъп до паметта при извикване на func1
Азащо изведнъж е cdecl?
> Защо изведнъж е този cdecl? aspxVisual Basic няма нищо общо с това. Работим по стандартите на Codegear.
> Visual Basic няма нищо общо с това
Е, зададох ви въпрос: защо избрахте споразумението cdecl при импортиране? Има ли разумна обосновка за това?
> защо избрахте конвенцията > при импортиране? cdeclзащото така трябва да бъде. Ако греша, моля, обяснете как да го направя правилно.
Ето DLL кода за яснота:
[КОД]#include #include #pragma hdrstop
#pragma argsused int WINAPI DllEntryPoint(HINSTANCE hinst, unsigned long reason, void* lpReserved) return 1; > //-------------------------------------------------------------------------- extern "C" bool __declspec( dllexport ) func1(unsigned char *input, unsigned char *output); extern " C" void __declspec(dllexport) test();
bool func1(unsigned char *input, unsigned char *output) ShowMessage((char *)input); input = output; >
void test() unsigned char *input = "test"; func1(input,input); >[/CODE]
Съобщение от Delphi:
[КОД]функция func1(вход: указател; изход: указател): bool; cdecl; външно "my.dll" име "_func1"; procedure test(); cdecl; външно "my.dll" име "_test";
procedure TForm1.Button1Click(Sender: TObject); var i :integer; s : низ; a: масив [0..30000] от char; b: ^uchar;
a2: масив [0..60000] от uchar; b2: ^uchar; begin StrCopy(a, "123456"); test(); //проверете извикването на func1 вътре в dll b := @a; b2 := @a2; func1(@a,@a2); //извикване на func1 от dll end;[/CODE]
При повикванеfunc1(@a,@a2); виждаме само знака "1", трябва да покажете цялото съдържание на масива.
Не съм сигурен, че с конвенцията за повикване по подразбиране в реда
extern "C" bool __declspec(dllexport) func1(неподписан char *вход, неподписан char *изход);
строителят използва cdecl конвенцията.
Ти самият сигурен ли си в това?
> bool func1(неподписан char *вход, неподписан char *изход) > > ShowMessage((char *)input); >вход = изход;> > >Хм, C++ копира ли съдържанието на паметта в този случай?
> Ти самият сигурен ли си в това?Да, дори и да го напишеш така, нищо не се променя: extern "C" bool __declspec( dllexport )__cdecl func1(unsigned char *input, unsigned char *output); extern "C" void __declspec( dllexport )__cdecl test();
> Хм, C++ копира ли съдържанието на паметта в този случай?> > вход = изход;да, няма значение.няма да копира памет. това не е въпросът. въпросът е защо виждаме само първия знак от входния масив, когато извикваме функция от delphi.
За какво е дебъгерът? Та умните чичковци от форума да компилират ненужния им DLL и да го дебъгват?
> За какво е дебъгерът? На умните чичковци във форума > компилираха DLL, от който не се нуждаеха, и го отстраниха?Ако не знаете отговора, моля, не замърсявайте темата. Просто обяснете как правилно да подадете указател към масив към dll файл. Хвърлете някаква статия, търсих в Google Интернет и не намерих нищо полезно за решаване на проблема.
благодаря на всички за участието. проблема решен. трябваше да бъде компилиран в delphi 7. (delphi 2009 не предава правилно указател към масив)
func1(вход: pchar; изход: pchar): bool;cdecl; външно "my.dll" име "_func1";
procedure TForm1.Button1Click(Sender: TObject); var a: array[0..40] of char; b: pchar; започнете a := "drtj2sdasdasdasd"; b := @a; func1(b,b); край;
> delphi 2009 неправилно предава указател към масиви къде звучи delphi 2009 във въпроса? там всъщност char е unicode
и никой не трябва да се интересува от основните условия на питащия) само губещите не ги знаят)
Индийските проблеми са си индийски проблеми. На шерифа не му пука.
Въпреки че, разбира се, това няма да реши проблема с масива, но може "неочаквано" да излезе при анализ на резултата.
←→Пийт ( 2009-07-10 17:44 ) [26]
bool в Delphi е 4 байта. boolean - един байт.
BOOL в C, както разбирам, имате предвид четири байта. Какво е bool в C?
> Pete (07/10/09 17:44) [26] > Какво е bool в C?В C няма bool. Но в C++ е така. Всичко е написано в книгите :) http://msdn.microsoft.com/en-us/library/tf4dy80a(VS.71,loband).aspx
И BOOL в C ++ за Windows обикновено се дефинира. Не знам за други операционни системи.
И все пак__declspec( dllexport)еstdcall. Може да се компилира сcdecl, но редът на параметрите ще бъде различен. Тогава ще бъдете много изненадани.
←→Домашен любимец ( 2009-07-13 11:58 ) [30]
> В C няма bool. Но в C++ е така. Всичко е написано в книгите > :)Всичко е страхотно. Но обратно към овцете. Ти каза:
bool в Delphi и bool в C++ - много различни
bool в Delphi е 4-байтов флаг, LongBool. Нулата се интерпретира като невярна, всичко различно от нула се интерпретира като вярно.
Според вас в C++ със сигурност е много по-различно. Аз иИсках да знам каква е разликата?
> каква е разликата?в MS VC може да бъде както 4, така и 1 байта. В строителя - не знам. Но подозирам, че ако имат общ VCL, тогава трябва да има съвместимост на типове
Съвсем наскоро се опитах да ги "трансплантирам" в "общия" VCL - благодаря, че Dup ме разубеди от ерес навреме и ме спаси от грях.
общо с Delphi, чрез състезание с предишни публикации.
←→Домашен любимец ( 2009-07-14 12:19 ) [37]
KSergey, значи най-накрая можеш да обясниш гледната си точка?
Как bool в C++ е толкова различен от bool в Delphi?
> Pete (07/14/09 12:19 PM) [37] > Как е толкова различен bool в C++ от bool в Delphi?Вече дадох линк, в раздела „Специфични за Microsoft“ всичко е описано подробно за C++. Също така доста определено написах за нечувствителността към малки и главни букви на единия и чувствителността на другия. Какво точно все още не е ясно?
←→Пийт ( 2009-07-16 12:28 ) [40]
Не стана ясно какво точно искаш да кажеш.
Искахте да кажете, че във VC++ преди версия 5.0 bool беше 4 байта, като се започне от петия стана един байт. BOOL е 4 байта навсякъде.
В Delphi bool е 4-байтов, а boolean е еднобайтов.
Правилно ли съм разбрала?
В Delphi Bool е общ тип, така че няма конкретен размер. Активиран за поддръжка на API
> Pete (07/16/09 12:28 PM) [40] > Правилно ли разбрах?Да. Не знаех за факта, че bool не винаги е еднобайтов в C++, преди да прочета тази връзка.
Е, вероятно Анатолий Подгорецки в [41] се изразява по-гамотично, но не знам значението на всички думи, написани там.
Между другото, в този смисъл, работете с BOOL- по-бързо! във всеки случай, когато преминавате към / от функцията, защото 4-байтова дума все още се предава и по време на проверки винаги се добавя команда за нулиране на горните 3 байта. за това как.
Не измисляйте, никакви три байта не се нулират, те ще бъдат проверени както са.
←→Пийт ( 2009-07-17 13:15 ) [44]
Изтрито от модераторЗабележка:последно предупреждение.