Calling Win32 DLL from C++
Calling Win32 DLL from C++
我是DLL世界的新手。我得到了一个Win32 DLL,它有很多功能。需要从C++调用这些DLL函数
我想调用CreateNewScanner
,它创建一个新的scanner对象并在C++中获得结果。DLL中提到的函数是:
BOOL CreateNewScanner(NewScanner *newScan);
并且NewScanner
是struct
,如下所述,
// 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??
}
}
首先,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);
无需摆弄LoadLibrary
、GetProcAddress
等。
如果要遵循LoadLibrary
/GetProcAddress
/FreeLibrary
方法,考虑以下"代码路径"(请注意,如果您有DLL公共头文件和相应的.lib文件,只需#include
公共DLL头,并与.lib文件链接,只需使用其原型在DLL头中定义的函数,就像使用从C++代码调用的普通C函数一样)。
为指向从DLL导出的函数的指针定义typedef
请注意,调用约定是指定的(通常,具有pure-C接口的Win32 DLL使用__stdcall
调用约定):
//
// Prototype of the DLL function, with *calling convention* specified
// (usually it's __stdcall for DLL with pure-C interface).
//
typedef BOOL (__stdcall *CreateNewScannerPtr)(NewScanner *);
然后尝试使用LoadLibrary
加载DLL:
//
// 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
获取函数指针:
//
// 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++,因此最好使用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模式,并定义一个带有析构函数的类,自动释放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
)的自动调用,代码是如何简化的,也是在错误路径的情况下。
- 如何解决"invalid conversion from 'char' to 'const char*'"
- std::async from std::async in windows xp
- std::is_reference from std::any
- std::time_point from and to std::string
- "No suitable conversion function from 'std::string' to 'const char *' exists"
- std::chrono::time_point from std::string
- Visual accept std::string from std::byte iterator
- C++中链表的错误"Abort signal from abort(3) (sigabrt) "
- dopen():不以 root 身份运行时"failed to map segment from shared object"
- C++ 中的"template <typename From, typename Tag> struct Alias;"是什么?
- from std::vector to adept::avector
- qt get child (Callout) from QChart
- Webassembly from Javascript
- Generate boost::uuids::uuid from boost::compute::detail::sha
- 什么是"Reading unbounded stream from standard input (Memory Management)"的例子
- Calling C++ dll from python
- 为什么我会收到"invalid conversion from 'Queue*/Stack*' to 'int'"错误消息?
- std::chrono 在从 main 或 from 类方法使用时给出不同的值
- Calling Python Script from Visual Studio C++ Solution
- Access C++ Enum from Swift