Страница 1 из 2
DLL
Добавлено: 08 дек 2004, 21:51
xpymep
Помогите пожалуйста! Я программирую недолго и столкнулся с такой проблемой: У меня есть какая-то длл и я никак не могу ее использовать..

. Код на писан на C++ Builder
Код: Выделить всё
bool success = false;
void *lib = LoadLibrary(AnsiString(GetCurrentDir()+"\\testdll.dll").c_str());
if (lib != NULL)
{
func = GetProcAddress(lib,"sleep");
success = (func != NULL);
if (success)
{
func ();
}
else
{
ShowMessage("Функция не загрузилась");
}
if(!FreeLibrary(lib))
{
ShowMessage("Память не освобождена");
}
А вот код дллки:
При работе программа не может загрузить функцию. Скажите пожалуйста где моя ошибка ?

Добавлено: 09 дек 2004, 11:41
Kolinus
По-моему результат функции GetProcAddress() надо приводить к нужному типу - типу функции
Добавлено: 09 дек 2004, 12:13
Romeo
Kolinus, проблема в том, что функция не может загрузиться, а не в том, что она не может правильно вызваться. xpymep, истоки скорее всего в том, что експортное имя функции в DLL не соответствует её "программному" имени. Например Visual C++ компилятор добавляет в конец имени число параметров и список типов параметров с определённым скриптованием. Для того, чтобы насильно задать экспортное имя нужно использовать def файл (опять таки этот выход именно для Visual C++). Ещё одно замечание, если DLL-ка сделана с поддержкой MFC, то приблема не возникает: MFC в своих дебрях это разруливает.
Добавлено: 09 дек 2004, 12:33
Eugie
xpymep, объяви свою функцию так:
Код: Выделить всё
extern "C" __export void __stdcall sleep(int s);
Добавлено: 09 дек 2004, 17:53
xpymep
Гы...Большое спасибо вам! Вся проблема была в объявлении func...
Код: Выделить всё
//У мя вначале было так :
int (__stdcall* func) (void);
//Естественно прога не могла найти такую функцию... Надо было так:
void (__stdcall* func) (int);
Да,кстати без объявления функции методом:
Код: Выделить всё
extern "C" __export void __stdcall sleep(int s);
в самой дллки,прога не работала,так что отдельное спасибо Eugie!
Да,кстати я пытался найти ошибку около месяца...при том работал на двух разных компах с разными примерами

и всеравно не работало

.
Еще вопросик: "Какая разница в использовании?":
Код: Выделить всё
void __export func();
extern "C" void __export func();
void __declspec(dllexport) func();
У мя первый вариант чаще всего работал (через раз,а оствльные вообще не работали). Да и имеет ли смылс менят __stdcall на __fastcal илиl __msfastcall в дллках, некоторые "спецы" (моя училка по программированию

) говорят,что если использовать не __stdcall, то функция будет работать стабильно. Так ли ? Ведь если использовать __fastcall можно было бы добиться более быстрой работы проги,используя extended регистры...
Добавлено: 09 дек 2004, 18:31
Eugie
"Какая разница в использовании?"...
__declspec(dllexport) - вариант MS
__export - Borland (в ранних версиях MS тоже использовался)
Объявление extern "C" задает тип связывания, характерный для C (т.е. без украшений имен в объектных файлах, как в C++). Это полезно, когда требуется вызывать функции, написанные на разных языках или из динамически загружаемых dll, как у тебя.
Вообще, есть два базовых понятия:
naming convention и
calling convention. Первое определяет, как будет выглядеть имя экспортируемой функции после компиляции, а второе - в как передаются параметры в функцию (порядок, кто организует т.н. стековый кадр и т.д.) Вещи это важные, как ты уже убедился

Если не согласовано первое, то просто ничего не соберется, т.к. линкер не найдет имени, которое ожидает. Если второе - еще хуже: соберется, но не будет работать.
О разнице между __stdcall и __fastcall - посмотри сам в MSDN. Насчет 'если использовать не __stdcall, то функция будет работать стабильно' - полная чушь. Еще на быстродействии это может сказаться, но уж никак не на стабильности.
Добавлено: 09 дек 2004, 18:47
Romeo
Верно, заявление о стабильности - бредни. Либо работает, либо не работает. Вызов функции - это не операционная система, чтобы говорить о её стабильности

.
Добавлено: 09 дек 2004, 20:52
xpymep
Сори..."апечатка" я имел ввиду нестабильно...

Еще такой вопрос... у мя есть форма:
.h file
Код: Выделить всё
#ifndef Unit1H
#define Unit1H
#include <Controls.hpp>
#include <StdCtrls.hpp>
#include <Forms.hpp>
//---------------------------------------------------------------------------
class Tformt : public TForm
{
__published: // IDE-managed Components
private: // User declarations
public: // User declarations
__fastcall Tformt(TComponent* Owner);
};
//---------------------------------------------------------------------------
extern Tformt *formt;
//---------------------------------------------------------------------------
#endif
.cpp file
Код: Выделить всё
//---------------------------------------------------------------------------
#include <vcl.h>
#include <windows.h>
#include "Unit1.h"
#pragma hdrstop
#pragma argsused
Tformt *formt ;
__fastcall Tformt::Tformt(TComponent* Owner)
: TForm(Owner)
{
}
extern "C" __export void __stdcall call(void)
{
Tformt *formt = new Tformt(NULL);
formt->ShowModal();
}
Вызываю функцию call в главном проэкте и мне показуют эксепшн:
EResNotFound "Resource Tformt not found"
Как понять ? Я вроде Tformt и ектсерном объявил, а потом еще и в сурс файле, в чем проблема ? Помогите плз!
О разнице между __stdcall и __fastcall - посмотри сам в MSDN
Про разницу я знаю, я просто имел ввиду стабильности этих префиксов. __stdcall - это (по идее, я могу быть не прав) когда компилятор использует 2-байтные регистры: ax,bx,cx,dx (тот кто программит на асм, мя поймет), а __fastcall - это использование 4-байтных (который используются Виндой и всеми 32-разрядными ОСями): eax,ebx,ecx,edx.
Добавлено: 10 дек 2004, 10:31
Absurd
Про разницу я знаю, я просто имел ввиду стабильности этих префиксов. __stdcall - это (по идее, я могу быть не прав) когда компилятор использует 2-байтные регистры: ax,bx,cx,dx (тот кто программит на асм, мя поймет), а __fastcall - это использование 4-байтных (который используются Виндой и всеми 32-разрядными ОСями): eax,ebx,ecx,edx.
Такого вызова - __fastcall в win32 вообще нет, это борландовское изобретение.
По-моему, оно рекоммендует компилятору вообще все параметры передать через регистры, не засовывая их в стек.
__stdcall - это нечто среднее между паскаль-образным и С- образным вызовом функции.
То есть параметры передаются в стек задом наперед, как в С, но очищает стек вызываемая функция, как в паскале.
Добавлено: 10 дек 2004, 17:39
xpymep
Согласен... На счет __fastcall я ошибся. Я просто больше программирую на Борланде и забываю об этом...
По-моему, оно рекоммендует компилятору вообще все параметры передать через регистры, не засовывая их в стек.
Не...в стэк стопудофф попадает. Если посмотреть дебаггером любую __fastcall функцию, то можно увидить pusha и popa в начале и конце функции. Иначе я себе не могу представить, как работали бы проги без стека...
Это конечно хорошо, но форма у мя до сих пор не работает.

Прошу вас помогите,плз!