2013-08-07 193 views
2

我是新来的DLL世界。我得到了一个Win32 DLL,它有很多功能。需要从C++调用这些DLL函数从C++调用Win32 DLL

我想调用CreateNewScanner,它创建一个新的扫描器对象并以C++获取结果。在DLL中提到 功能是:

BOOL CreateNewScanner(NewScanner *newScan); 

NewScannerstruct,如下,

// Structure NewScanner is defined in "common.h" . 
typedef struct{ 
    BYTE host_no; // <- host_no =0 
    LONG time; // <- command timeout (in seconds) 
    BYTE status; // -> Host adapter status 
    HANDLE obj; // -> Object handle for the scanner 
}NewScanner; 

我如何调用这个函数?开始使用C++,这里是我管理的,

#include <iostream> 
#include <windows.h> 
using namespace std; 
int main(){ 
    HINSTANCE hInstance;  
    if(!(hInstance=LoadLibrary("WinScanner.dll"))){ 
     cout << "could not load library" << endl;   
    } 
    /* get pointer to the function in the dll*/ 
    FARPROC handle = GetProcAddress(HMODULE(hInstance), "CreateNewScanner"); 
    if(!handle){ 
    // Handle the error 
    FreeLibrary(hInstance); 
    return "-1"; 
    }else{  
    // Call the function 
    //How to call here?? 
    } 
} 
+0

我编辑了这个问题只是添加更好的文本格式。 –

回答

5

首先,return "-1"是不好的。您需要返回一个整数。所以你的意思是return -1

现在的问题。不是将函数指针声明为FARPROC,而是将其声明为函数指针类型更容易。

typedef BOOL (*CreateNewScannerProc)(NewScanner*); 

然后调用GetProcAddress这样的:

HMODULE hlib = LoadLibrary(...); 
// LoadLibrary returns HMODULE and not HINSTANCE 
// check hlib for NULL 

CreateNewScannerProc CreateNewScanner = 
    (CreateNewScannerProc) GetProcAddress(hlib, "CreateNewScanner"); 
if (CreateNewScanner == NULL) 
    // handle error 

// now we can call the function 
NewScanner newScan; 
BOOL retval = CreateNewScanner(&newScan); 

说到这一切,通常是一个图书馆将配备一个头文件(你显然不这样你就应该包括它)和的.lib文件用于加载时链接。请确保你的.lib文件传递给你的链接,你可以简单地这样做:

#include "NameOfTheHeaderFileGoesHere.h" 
.... 
NewScanner newScan; 
BOOL retval = CreateNewScanner(&newScan); 

无需更动LoadLibraryGetProcAddress等。

+1

请注意,我使用C风格转换,因为我不确定提交者是否已经准备好了C++风格演员。 –

2

如果你想跟着LoadLibrary/GetProcAddress/FreeLibrary方法,考虑下面的“代码路径”(请注意,如果你有DLL公众头文件和相应的.lib文件,只需#include公众DLL头,和链接到.lib文件,只需使用在DLL头中定义了原型的函数,就像使用从C++代码调用的普通C函数那样)。

定义指向从DLL导出的函数的指针的typedef
注意,调用约定指定(通常的Win32 DLL的纯-C接口使用__stdcall calling convention):

// 
// Prototype of the DLL function, with *calling convention* specified 
// (usually it's __stdcall for DLL with pure-C interface). 
// 
typedef BOOL (__stdcall *CreateNewScannerPtr)(NewScanner *); 

然后尝试加载DLL使用LoadLibrary

// 
// Try loading the DLL. 
// 
HMODULE hDll = LoadLibrary(L"WinScanner.dll"); // <--- Note the use of L"..." for Unicode 
if (! hDll) 
{ 
    .... error 
} 

请注意,DLL的文件名是一个Unicode字符串(请注意L"..."装饰)。一般来说,您应该在现代C++/Win32代码中使用Unicode。

这时可以尝试得到使用函数指针GetProcAddress:使用C++

// 
// Try getting the pointer to CreateNewScanner DLL function. 
// 
auto pCreateNewScanner = reinterpret_cast<CreateNewScannerPtr> 
(
    GetProcAddress 
    (
    hDll,    // DLL handle 
    "CreateNewScanner" // Function name 
) 
); 

if (! pCreateNewScanner) 
{ 
    .... error 

    // Release the DLL 
    FreeLibrary(hDll); 

    // Avoid dangling references 
    hDll = nullptr; 
} 

注意,因为使用的是C++,它的更好 - 风格转换(如reinterpret_cast<>在这种情况下) ,而不是旧的C型演员。
此外,由于函数指针的类型reinterpret_cast中指定,因此在语句的开头处重复使用它无用,因此可以使用新的C++ 11的关键字auto

您可以使用返回的函数指针调用DLL函数:

BOOL retCode = pCreateNewScanner(....); 

// Note: some other common prefix used in this case is "pfn" 
// as "pointer to function" (e.g. pfnCreateNewScanner). 

一旦你使用DLL完成后,您可以释放它,调用FreeLibrary

// 
// Release the DLL 
// 
FreeLibrary(hDll); 
hDll = nullptr; 

另外,请注意,您可以使用C++ RAII pattern,并用一个析构函数自动定义一个类释放DLL(这简化了管理库加载/释放部分的代码)。
例如

class RaiiDll 
{ 
public: 
    // Load the DLL. 
    explicit RaiiDll(const std::wstring& filename) // may also provide an overload 
                // with (const wchar_t*) 
    { 
     m_hDll = ::LoadLibrary(filename.c_str()); 
     if (! m_hDll) 
     { 
      // Error 
      throw std::runtime_error("Can't load the DLL - LoadLibrary() failed."); 
      // .... or use some other exception... 
     } 
    } 

    // Safely and automatically release the DLL. 
    ~RaiiDll() 
    { 
     if (m_hDll) 
     { 
      ::FreeLibrary(m_hDll); 
      m_hDll = nullptr; 
     } 
    } 

    // Get DLL module handle. 
    HMODULE Get() const 
    { 
     return m_hDll; 
    } 

private: 
    HMODULE m_hDll; // DLL instance handle 

    // 
    // Ban copy (if compiler supports new C++11 =delete, use it) 
    // 
private: 
    RaiiDll(RaiiDll &); 
    RaiiDll & operator=(RaiiDll &); 
}; 

然后,在一些代码块,你可以有:

{ 
    // Load the library (throws on error). 
    RaiiDll scannerDll(L"WinScanner.dll"); 

    // Get DLL function pointer 
    auto pCreateNewScanner = reinterpret_cast<CreateNewScannerPtr>( 
     GetProcAddress(scannerDll.Get(), "CreateNewScanner")); 
    if (! pCreateNewScanner) 
    { 
     .... error.  
    } 

    .... use the function 

} // <--- DLL automatically released thanks to RaiiDll destructor!!! 

注意如何代码简化感谢自动调用RaiiDll destrutor(等的FreeLibrary),也错误路径的情况。