Вызов функции DLL

  • Автор темы Decembrist
  • Дата начала
Статус
Закрыто для дальнейших ответов.
D

Decembrist

Гость
#1
Функция DLL возвращает указатель на значение например float* function f1(); Как ее вызвать в EXE программе?
 
B

bugger

Гость
#2
Код:
typedef float* ( CALLBACK* LPFNDLLFUNC1 )( VOID );
LPFNDLLFUNC1 lpfnDllFunc1;

HINSTANCE dllhinst;
dllhinst = LoadLibrary( "mydll" );
lpfnDllFunc1 = ( LPFNDLLFUNC1 )GetProcAddress( dllhinst, "f1" );

float* pMyFloat = f1();
 
M

Mustang

Гость
#3
а по моему лучше сразу брать оттуда значение.
ибо подумайте о дальнейшей судьбе памяти (под возвращаемый указатель), если она выделяется в самой функции...
 
S

Serge

Гость
#4
Грабли вроде в том, что, получив адрес, вызов функции будет:
float* pMyFloat = lpfnDllFunc1();
лучше будет:
typedef float* (*LPFNDLLFUNC1)(void);
но думается, что грабли будут еще в том, что Вы ничего не вернете из фун., т.к. этих данных уже не будет существовать. Вы должны объявить exp. данные и записать в них другой функцией, используя данную фун.
Вообще в С++ указатели из фун. не возвращаются - будут проблемы.
Ну, может, что не так понял.
 
S

Serge

Гость
#5
Да, если уж приспичело вернуть указатель, то попробуйте на возврате фун. разименовать и происвоить другой переменной. На практике не делал, но должно получиться.
 
M

Mustang

Гость
#6
Вообще в С++ указатели из фун. не возвращаются - будут проблемы.
вообще-то не совсем так. они-то возвращаются, если объявлены снаружи, а в функции просто изменяетсяих состояние или выделяется память.
и то с выделением памяти в функциях в своих длл стоит быть аккуратным.
 
S

Serge

Гость
#7
Я и не имел в виду, что они не возвращаются, в принципе. Просто раньше наступил несколько раз на грабли и стараюсь не чесать левой рукой правое ухо.
 
P

Pete

Гость
#8
typedef float* ( CALLBACK* LPFNDLLFUNC1 )( VOID );
LPFNDLLFUNC1 lpfnDllFunc1;

HINSTANCE dllhinst;
dllhinst = LoadLibrary( "mydll" );
lpfnDllFunc1 = ( LPFNDLLFUNC1 )GetProcAddress( dllhinst, "f1" );
Народ объясните зачем вы используете такой изврат??? Данный подход используется лишь когда у вас нет lib'a искомой DLL. Когда dll-ка ваша, у вас по опередлению есть lib файл. В VC ставите использовать динамическую линковку, подключаете lib и все , и будет вам счастье, надо только dll-ку положить куда следует или path прописать.

Код:
и то с выделением памяти в функциях в своих длл стоит быть аккуратным
Аккуратным надо быть ровно на столько насколько это требуется в exe файлах, а именно: не забывать ее освобождать. DLL-ка мапится в адресное пространство того исполняемого модуля который ее загрузил и все адреса доступные exe доступны и dll, и не надо никакой мистики.
 
B

bugger

Гость
#9
LoadLibrary имеет определенные преимущества перед просто линковкой lib файлов. если lib приаттачиваешь к проекту, то исполняемый файл увеличится на размер твоей библиотеки. а ведь частенько бывает, что все экспортируемые функции и не надо использовать, а только часть из них. если использовать LoadLibrary, то ты подгружаешь только те функции, которые тебе нужны и только тогда, когда они тебе нужны. размер исполняемого файла при этом не увеличивается. кроме того, либины, которые были написаны при помощи другого компилятора ты можешь и не подключить из за того, что есть нюансы.
 
P

Pete

Гость
#10
если lib приаттачиваешь к проекту, то исполняемый файл увеличится на размер твоей библиотеки
Я же сказал что надо ставить Динамическую Линковку, а lib используется только для определения смещения, читай адреса вызываемой функции в длл, то что делает
Код:
lpfnDllFunc1 = ( LPFNDLLFUNC1 )GetProcAddress( dllhinst, "f1" );
. Статическая линковка да дает увеличение исполняемого файла, на то она и статическая.

если использовать LoadLibrary, то ты подгружаешь только те функции, которые тебе нужны и только тогда, когда они тебе нужны
Нет, как только ты делаешь loadlibrary вся dll мапится в адресное пространство твоего процесса. В винде нет возможности частичной подгрузки функций. Не понятно как это вообще можно реализовать, читать кусок длл?, но тогда все будет работать очень медленно, каждый вызов функции - обращение к диску, зачем же все так усложнять. Хочешь - делай несколько dll, но выигрыша реального не получишь, если у тебя dll не мегабайтные.

кроме того, либины, которые были написаны при помощи другого компилятора ты можешь и не подключить из за того, что есть нюансы.
Но это только в случае если ты юзаешь чужую либину, обычно командные проекты пишутся с использованием одних средств разработки, это определяется в спецификации на проект. Зачем увеличивать количество глюков в программе, если этого можно избежать.

Я когда-то тоже по незнанию использовал выше означеный способ, но потом понял, что есть путь гораздо проще, и большинство делают именно как написал я, так как код читать гораздо проще и глюков меньше с типами данных. А то уже какие-то проблемы с указателями пошли...., я передаю **p в функцию dll, выделяю память, а потом освобождаю в exe и НИКАКИХ проблем.

Так выглядит объявление простой функции в dll модуле:

Код:
#ifdef CVLIB_EXPORTS
#define CVLIB_API __declspec(dllexport)
#else
#define CVLIB_API __declspec(dllimport)
#endif

int CVLIB_API ubGaussSmoothing64f(unsigned char* src, double* dst,  unsigned int width, unsigned int height, double sigma);
А так вызов:

Код:
ubGaussSmoothing64f(src, dst, width, height, sigma);
Предложенный вами способ оправдано использовать когда у вас нет h-файла и lib-файла. В своих проектах использовать такой подход неоправдано, лишний гемор.
 
Статус
Закрыто для дальнейших ответов.