tomas850
一般會員
發表:12 回覆:16 積分:5 註冊:2004-01-05
發送簡訊給我
|
第一次用LoadLibrary實作,有點問題想要請教一下。
是不是只要用LoadLibrary()就可以不用管這個DLL是
在VC下或是BCB下實作出來的?? 例如原本在VC下使用的"TESTDLL.DLL"
我在BCB下這樣寫 HINSTANCE dllHandle;
typedef void(CALLBACK* TDLLFUNCTION)(void);
TDLLFUNCTION TDLLSet;
dllHandle = NULL;
TDLLSet = NULL;
dllHandle = LoadLibrary("testdll.dll");
TDLLSet = (TDLLFUNCTION)GetProcAddress(dllHandle,"SetDut"); 是不是這樣就可以捉出TESTDLL.DLL中的SetDut()來用?
因為翻之前的文章好像說使用loadlibrary()就不用特地去轉換VC
那邊過來的DLL檔,不知是不是這樣。 我用上面的方式組譯起來是沒有語法的問題,
但在最後Link的時候會出現
Unresolved external 'SetDut(int)' reference from E:\......... 第一次用loadlibrary(),說了一堆也不知道有沒有人看的懂。
|
taishyang
站務副站長
發表:377 回覆:5490 積分:4563 註冊:2002-10-08
發送簡訊給我
|
|
luckfox
一般會員
發表:34 回覆:40 積分:24 註冊:2002-10-15
發送簡訊給我
|
包子大大寫的粉好,沒有啥需要補充的,但是我用的方法可能更簡單
在做好VC的DLL檔後,直接用VC的dumplib觀看他的實際函式名字
D:\BCB_share\Porject\UI_SoftGate2\SoftGate_API>dumpbin /exports softapapi.dll Section contains the following exports for SoftApApi.dll 0 characteristics
404C5B2C time date stamp Mon Mar 08 19:38:20 2004
0.00 version
1 ordinal base
2 number of functions
2 number of names ordinal hint RVA name 1 0 00001210 ?GetFirmwareVersion@@YGFPAD@Z
2 1 00001200 ?TestDll@@YGXXZ typedef int (*GETVER)(char *);
void __fastcall TForm1::Button1Click(TObject *Sender)
{
HINSTANCE dll;
GETVER GetVer;
int RTV;
char VerString[1024];
AnsiString DllPathName; DllPathName=AppPath SoftGate_API_Path "SoftApApi.dll";
dll=LoadLibrary(DllPathName.c_str());
if(dll!=NULL)
{
GetVer=(GETVER)GetProcAddress(dll, "?GetFirmwareVersion@@YGFPAD@Z");//直接引用
if(GetVer!=NULL)
{
RTV=GetVer(VerString); Edit29->Text(AnsiString(VerString));
}
else
{
Edit29->Text("GetVer Fail");
}
FreeLibrary(dll);
}
else
{
Edit29->Text("Load Dll Fail");
} }
|
tomas850
一般會員
發表:12 回覆:16 積分:5 註冊:2004-01-05
發送簡訊給我
|
剛看了RaynoPao發表的那篇文章,
我做的應該就是他所提到的第四大部份吧!
我也有把他的source code下載來看,
感覺我的用法應該沒有錯誤耶~~~~~~ 只是不知為啥在最後的link階段,我從dll中引用的function都會是
[Linker Error] Unresolved external'TForm1::(DLL引用的函數名稱)..... 唯一我覺的有點奇怪的是,在RaynoPro的範例中,
他在從DLL中引用了AddMethodEx(),並不用在.H的檔案中再次定義該函數原型。
而我沒有再次定義的話,會出現
Call to undefined fuction的錯誤。
|
markov
中階會員
發表:55 回覆:135 積分:53 註冊:2003-12-01
發送簡訊給我
|
應該先將visual c 的dll利用implib轉成bcb可以看的懂的形式
|
tomas850
一般會員
發表:12 回覆:16 積分:5 註冊:2004-01-05
發送簡訊給我
|
引言:
應該先將visual c 的dll利用implib轉成bcb可以看的懂的形式
我看書上的寫法是說,要載入DLL的方式有二種。
一種是靜態的連結:
若是Visual C 的DLL,要利用implib和coff2omf來轉換格式。
另一種是動態連結:
這種方式並不須要做轉換的動作。而我用的是動態的連結方式。
不知道這種說法對不對......... 另外我覺得問題可能是出在這種地方吧 >
今天朝這個方面去找找看。
|
ENIX007
高階會員
發表:28 回覆:274 積分:185 註冊:2003-11-27
發送簡訊給我
|
tomas850您好
引言: HINSTANCE dllHandle;
typedef void(CALLBACK* TDLLFUNCTION)(void);
TDLLFUNCTION TDLLSet;
dllHandle = NULL;
TDLLSet = NULL;
dllHandle = LoadLibrary("testdll.dll");
TDLLSet = (TDLLFUNCTION)GetProcAddress(dllHandle,"SetDut");
請看紅色部分,typedef定義函式指標型態,為的是讓您的TDLLSet能接收DLL內部
函式的位址,因此DLL內部函式是什麼型態,TDLLSet就必須是什麼型態...
因此除非您6種DLL內函式型態都一樣,否則一定會發生錯誤的...
另外照小弟所學,BCB呼叫VC的DLL應該不需額外步驟,只要DLL內匯出前加上
extern "C"關鍵字,不使用編譯器的name mangling即可 程式迷人之處,在於邏輯思考,然而卻也是惱人之處~~
------ 程式迷人之處,在於邏輯思考,然而卻也是惱人之處~~
|
tomas850
一般會員
發表:12 回覆:16 積分:5 註冊:2004-01-05
發送簡訊給我
|
實在找不出問題點,把我的source code放上來給大家看一下有沒有什麼問題。
方法一:使用靜態連結,已將原testdll.dll用implib轉出BCB使用的testdll.lib並add到project裡面。 #include
#pragma hdrstop #include "Unit1.h"
//--------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
extern "C" __declspec(dllimport) int SetThisCardAsDut(int nCardIndex);
extern "C" __declspec(dllimport) int EnableDutCard(int nCardIndex);
extern "C" __declspec(dllimport) int SetDriverTestMode(int nCardIndex);
extern "C" __declspec(dllimport) int SetDriverTestMode(int nCardIndex);
extern "C" __declspec(dllimport) int ReadEEPRom16(int nCardIndex, int offset, int* vlaue);
TForm1 *Form1;
//--------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{ }
//-------------------------------------------------------------------- void __fastcall TForm1::Button1Click(TObject *Sender)
{
m_nCardIndex = 1;
SetThisCardAsDut(m_nCardIndex);
EnableDutCard(m_nCardIndex);
SetDriverTestMode(m_nCardIndex);
GetMACAddress();
// GetCountryCode();
}
//--------------------------------------------------------------------
void TForm1::GetMACAddress()
{
int tempInt[6]={0},i;
int shortArray[3]={0};
int *temp;
AnsiString MacString;
int iAdapter = 1;
int status;
ReadEEPRom16(iAdapter, 0x10, temp);
shortArray[0]=*temp;
ReadEEPRom16(iAdapter, 0x11, temp);
shortArray[1]=*temp;
ReadEEPRom16(iAdapter, 0x12, temp);
shortArray[2]=*temp; MAC1->Text=shortArray[0];
MAC2->Text=shortArray[1];
MAC3->Text=shortArray[2];
}
//-------------------------------------------------------------------- 廠商提供的.h file
/*
** $Id: testDll.h 1.12 2003/06/10 02:15:38Z juji Exp $
*/ /*********************************************************************
* Copyright (c) 2002 Integrated Programmable Communications, Inc.
*
* All rights reserved. Copying, compilation, modification, distribution
* or any other use whatsoever of this material is strictly prohibited
* except in accordance with a Software License Agreement with
* Integrated Programmable Communications, Inc.
*********************************************************************/
/*********************************************************************
GENERAL DESCRIPTION
********************
1. RF test main procedure implementation.
2. The export dll function should be in 'C' language (not C ), for the ease of use
in other language (VB, Pascal...)
3. In this version, .def is not used but "__declspec(dllexport)" instead
4. This version of DLL functions can be called either by InProComm RF Test Utility or
3rd party's application, which wraps with a language-independant, upgradable
intermediate layer
*/ /*********************************************************************
* F U N C T I O N D E C L A R A T I O N S
**********************************************************************
*/
/// BB registers
int ReadBBReg8(int nCardIndex, int offset, int* ucValue);
int WriteBBReg8(int nCardIndex, int offset, int ucValue); /// EEPRom
int BurnEEPRomFromFile(int nCardIndex, char* fileName);
int ReadEEPRom16(int nCardIndex, int offset, int* value);
int WriteEEPRom16(int nCardIndex, int offset, int usValue);
int GetEEPRomSize(int nCardIndex, int* value); ///// Testing functions of RFTest
//extern "C" __declspec(dllexport) int DisableWlanDll();
int StandBy(int nCardIndex);
int ContinuousPktTx(int nCardIndex, char* szBuf, int bufSize, int txRate, int pktCount, int pktInterval, int txPwr);
int qryTxStatus(int nCardIndex, long *sentCount);
int qryRxStatus(int nCardIndex, int *rxOk_p, int *rxCrcErr_p, int *rxPauReceive_p, int *rxPauFcsErr_p, int *rxCcaCount_p);
int setChannel(int nCardIndex, int channelConfig);
int SetDriverTestMode(int nCardIndex);
int SetDriverNormalMode(int nCardIndex);
int qryChannel(int nCardIndex, int *channelConfig_p);
int setRxDMA(int nCardIndex, int condition, int nAntenna);
int qryCR62MeanVar(int nCardIndex, int *cr62Mean_p, int *cr62Var_p); int OutputPower(int nCardIndex, int nTxRate);
int LocalFrequecyMeasure(int nCardIndex);
int CarrierSuppressionMeasure(int nCardIndex, int nModulationType, int nTxRate); int SetTxFilter(int nCardIndex, int iFilterType, int iChannel);
int SetRxAntenna(int nCardIndex, int iAntennaType);
int PowerSave(int nCardIndex, int iEnable); int SetDrvDescName(char* pchDrvDesc);
int GetDriverUsedIndex(); //// functions to manipulate Agilent DUT shielding box interface
int DisableDutCard(int nCardIndex);
int EnableDutCard(int nCardIndex); int DeActiveDut(int nCardIndex);
int ActiveDut(int nCardIndex);
int SetThisCardAsDut(int nCardIndex);
int SetThisCardAsDutWithTi(int nCardIndex); int InitTxCalibration(int nCardIndex, int nGain);
double TXIQCalibration(int Step, char *w0s, char* wnks, char *wpks, int nCardIndex);
int InitRxCalibration(int nCardIndex);
double SetRxCalibrationParam(int Step, int Gain, int nCardIndex);
double RFRxCalibration(int Step, int LoopCount, int nCardIndex);
int StopRFCalibration(int nCardIndex); int SaveTxPowerToEeprom(int nCardIndex, int nChannel, int bCck, int nTxPwr);
int ReadTxPowerFromEeprom(int nCardIndex, int nChannel, int bCck, char* nTxPwr); int SaveRFCalTabToEEPROM(int nCardIndex, int nChannel); 方法二:動態連結 //-------------------------------------------------------------------- #include
#pragma hdrstop #include "Unit1.h"
//--------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
//--------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{
}
//-------------------------------------------------------------------- void __fastcall TForm1::Button1Click(TObject *Sender)
{
m_nCardIndex = 1;
SetThisCardAsDut(m_nCardIndex);
EnableDutCard(m_nCardIndex);
SetDriverTestMode(m_nCardIndex);
GetMACAddress();
}
//--------------------------------------------------------------------
void TForm1::DllLoad()
{
dllHandle = NULL;
typedef int(*TDLLFUNCTION1)(int);
typedef int(*TDLLFUNCTION3)(int,int,int*);
typedef int(*TDLLFUNCTION4)(int,int,int);
TDLLFUNCTION1 TDLLSetDut,TDLLEnabledDut,TDLLDisabledDut,TDLLSetTestMode,TDLLSetNormalMode;
TDLLFUNCTION3 TDLLReadEPPE16;
TDLLFUNCTION4 TDLLWriteEPPE16;
TDLLSetDut = NULL, TDLLEnabledDut = NULL, TDLLDisabledDut = NULL, TDLLSetTestMode = NULL,
TDLLSetNormalMode = NULL, TDLLReadEPPE16 = NULL, TDLLWriteEPPE16 = NULL;
dllHandle = LoadLibrary("testdll.dll");
if( dllHandle != NULL )
{
TDLLSetDut = (TDLLFUNCTION1)GetProcAddress(dllHandle,"SetThisCardAsDut");
TDLLEnabledDut = (TDLLFUNCTION1)GetProcAddress(dllHandle,"EnableDutCard");
TDLLDisabledDut = (TDLLFUNCTION1)GetProcAddress(dllHandle,"DisableDutCard");
TDLLSetTestMode = (TDLLFUNCTION1)GetProcAddress(dllHandle,"setDriverTestMode");
TDLLSetNormalMode = (TDLLFUNCTION1)GetProcAddress(dllHandle,"setDriveNormalMode");
TDLLReadEPPE16 = (TDLLFUNCTION3)GetProcAddress(dllHandle,"ReadEEPRom16");
TDLLWriteEPPE16 = (TDLLFUNCTION4)GetProcAddress(dllHandle,"WriteEEPRom16");
if(TDLLSetDut == NULL)
ShowMessage(" .dll loading failure please check .dll file is exist");
if(TDLLEnabledDut == NULL)
ShowMessage(" .dll loading failure please check .dll file is exist");
if(TDLLDisabledDut == NULL)
ShowMessage(" .dll loading failure please check .dll file is exist");
if(TDLLSetTestMode == NULL)
ShowMessage(" .dll loading failure please check .dll file is exist");
if(TDLLSetNormalMode == NULL)
ShowMessage(" .dll loading failure please check .dll file is exist");
if(TDLLReadEPPE16 == NULL)
ShowMessage(" .dll loading failure please check .dll file is exist");
if(TDLLWriteEPPE16 == NULL)
ShowMessage(" .dll loading failure please check .dll file is exist");
}
}
//--------------------------------------------------------------------
void TForm1::GetMACAddress()
{
int tempInt[6]={0},i;
int shortArray[3]={0};
int *temp;
AnsiString MacString;
int iAdapter = 1;
int status;
ReadEEPRom16(iAdapter, 0x10, temp);
shortArray[0]=*temp;
ReadEEPRom16(iAdapter, 0x11, temp);
shortArray[1]=*temp;
ReadEEPRom16(iAdapter, 0x12, temp);
shortArray[2]=*temp; MAC1->Text=shortArray[0];
MAC2->Text=shortArray[1];
MAC3->Text=shortArray[2];
}
//--------------------------------------------------------------------
void __fastcall TForm1::FormActivate(TObject *Sender)
{
DllLoad();
}
//-------------------------------------------------------------------- 二種方法試的結果都是一樣的。 [Linker Error] Unresolved external 'TForm1::SetThisCardAsDut(int)' referenced from E:\WIRELESS\WA4270\MAC&COUNTRY_CODE_BCB\UNIT1.OBJ
[Linker Error] Unresolved external 'TForm1::EnableDutCard(int)' referenced from E:\WIRELESS\WA4270\MAC&COUNTRY_CODE_BCB\UNIT1.OBJ
[Linker Error] Unresolved external 'TForm1::SetDriverTestMode(int)' referenced from E:\WIRELESS\WA4270\MAC&COUNTRY_CODE_BCB\UNIT1.OBJ
[Linker Error] Unresolved external 'TForm1::ReadEEPRom16(int, int, int *)' referenced from E:\WIRELESS\WA4270\MAC&COUNTRY_CODE_BCB\UNIT1.OBJ
|
ENIX007
高階會員
發表:28 回覆:274 積分:185 註冊:2003-11-27
發送簡訊給我
|
------ 程式迷人之處,在於邏輯思考,然而卻也是惱人之處~~
|
tomas850
一般會員
發表:12 回覆:16 積分:5 註冊:2004-01-05
發送簡訊給我
|
引言:
typedef int(__stdcall *TDLLFUNCTION1)(int);
typedef int(__stdcall *TDLLFUNCTION3)(int,int,int*);
typedef int(__stdcall *TDLLFUNCTION4)(int,int,int);
我試著改成上述的方式也是不能用,(__cdcel我也順便試了一下,也是不行)
後來我去翻廠商提供的範例程式(Visual C )。廠商是這樣寫的 #define DECLARE_FUNCTION0(retVal, FuncName)
typedef retVal (*TYPE_##FuncName)();
TYPE_##FuncName m_##FuncName;
short m_is##FuncName;
retVal FuncName()
{
if (m_dllHandle)
{
if (FUNC_LOADED != m_is##FuncName)
{
m_##FuncName = NULL;
m_##FuncName = (TYPE_##FuncName)GetProcAddress(m_dllHandle, #FuncName);
m_is##FuncName = FUNC_LOADED;
}
if (NULL != m_##FuncName)
return m_##FuncName();
else
return (retVal)NULL;
}
else
return (retVal)NULL;
} #define DECLARE_FUNCTION1(retVal, FuncName, Param1)
typedef retVal (*TYPE_##FuncName)(Param1);
TYPE_##FuncName m_##FuncName;
short m_is##FuncName;
retVal FuncName(Param1 p1)
{
if (m_dllHandle)
{
if (FUNC_LOADED != m_is##FuncName)
{
m_##FuncName = NULL;
m_##FuncName = (TYPE_##FuncName)GetProcAddress(m_dllHandle, #FuncName);
m_is##FuncName = FUNC_LOADED;
}
if (NULL != m_##FuncName)
return m_##FuncName(p1);
else
return (retVal)NULL;
}
else
return (retVal)NULL;
} #define DECLARE_FUNCTION2(retVal, FuncName, Param1, Param2)
typedef retVal (*TYPE_##FuncName)(Param1, Param2);
TYPE_##FuncName m_##FuncName;
short m_is##FuncName;
retVal FuncName (Param1 p1, Param2 p2)
{
if (m_dllHandle)
{
if (FUNC_LOADED != m_is##FuncName)
{
m_##FuncName = NULL;
m_##FuncName = (TYPE_##FuncName)GetProcAddress(m_dllHandle, #FuncName);
m_is##FuncName = FUNC_LOADED;
}
if (NULL != m_##FuncName)
return m_##FuncName(p1, p2);
else
return (retVal)NULL;
}
else
return (retVal)NULL;
} 他們只區分所以函數參數的個數來套用到所有的函數中。
但說真的我看不懂他到底是寫些什麼。 發表人 - tomas850 於 2004/03/10 16:13:55
|
ENIX007
高階會員
發表:28 回覆:274 積分:185 註冊:2003-11-27
發送簡訊給我
|
tomas850您好
突然發現,您Post的source code基本上是沒問題的,但若真的要使用這些函式的話,
就會產生問題了,因為所有的宣告(包括typedef)都寫在TForm1::DllLoad函式內,
只要離開這個函式,那些宣告的函式已經脫離它們的scope了,因此別的地方是無法
使用的...
不過您的問題好像不在這裡... 程式迷人之處,在於邏輯思考,然而卻也是惱人之處~~
------ 程式迷人之處,在於邏輯思考,然而卻也是惱人之處~~
|
tomas850
一般會員
發表:12 回覆:16 積分:5 註冊:2004-01-05
發送簡訊給我
|
引言:
tomas850您好
突然發現,您Post的source code基本上是沒問題的,但若真的要使用這些函式的話,
就會產生問題了,因為所有的宣告(包括typedef)都寫在TForm1::DllLoad函式內,
只要離開這個函式,那些宣告的函式已經脫離它們的scope了,因此別的地方是無法
使用的...
不過您的問題好像不在這裡... 程式迷人之處,在於邏輯思考,然而卻也是惱人之處~~
>>< face="Verdana, Arial, Helvetica">
真的非常的感謝ENIX007的幫忙,
我陸續的有在試各種方法來解決這個問題,
剛也有把所有的typedef和宣告都移到.h的檔案去。
現在我是可以執行出執行檔出來了。
但一但呼叫到DLL的函數時,就會出現下面的問題。 Error
Project BurnMac.exe raised exception class EAcccess Violation with message 'Access violation at address 1000666A in module 'testdll.dll'
Read of address 00000008'.Process stopped.Use Step or Run to continue. 其實上面那個error應該是要post圖片上來,但我不知道怎上傳......
|
ENIX007
高階會員
發表:28 回覆:274 積分:185 註冊:2003-11-27
發送簡訊給我
|
tomas850您好
記憶體存取錯誤...這個就麻煩了...
這個時候只能單步trace囉...只要確定LoadLibrary()出來所接收到的函式
不是NULL,就表示讀取DLL流程OK!
看來您也無法trace到DLL內部吧,我的方法是,找出當在哪個函式,檢查進入
函式前所有引數是否正確,如果都沒問題,再來只能詢問廠商了吧... 程式迷人之處,在於邏輯思考,然而卻也是惱人之處~~
------ 程式迷人之處,在於邏輯思考,然而卻也是惱人之處~~
|
tomas850
一般會員
發表:12 回覆:16 積分:5 註冊:2004-01-05
發送簡訊給我
|
引言:
tomas850您好
記憶體存取錯誤...這個就麻煩了...
這個時候只能單步trace囉...只要確定LoadLibrary()出來所接收到的函式
不是NULL,就表示讀取DLL流程OK!
看來您也無法trace到DLL內部吧,我的方法是,找出當在哪個函式,檢查進入
函式前所有引數是否正確,如果都沒問題,再來只能詢問廠商了吧... 程式迷人之處,在於邏輯思考,然而卻也是惱人之處~~
>>< face="Verdana, Arial, Helvetica"> 嗯~~真的是DLL的內容有問題,有某些函式是無法使用的,
亦或是應該說某些函式是在特定環境下才能使用......
現在已經確定在
|