在 C++ 中的不同项目文件中将参数)传递给函数)
Passing parameter(s) to function(s) withing different project files in C++
我只是对将参数传递给不同项目的 C++ 函数感到困惑。
我有两种不同的方案,一种是DLL工程,另一种是Console工程。在第一个项目中,我有一段代码如下:
class __declspec(dllexport) FormatLog
{
public:
void __cdecl ParseFormat(LPCWSTR);
};
其余的代码在这里并不重要,而在第二个项目中我有包含以下代码的头文件:
class FormatImpl
{
public:
typedef void (__cdecl * FORMAT) (LPCWSTR);
HINSTANCE hModule;
FORMAT Format;
FormatImpl()
{
hModule = LoadLibrary(L"FormatLog.dll");
if (hModule != NULL)
{
Format = (FORMAT) GetProcAddress(hModule, "?ParseFormat@FormatLog@@XXXXXXXX@X");
}
}
~FormatImpl()
{
if (hModule != NULL)
{
FreeLibrary(hModule);
}
}
};
当我使用以下代码从主函数调用它时:
int main(int argc, char* argv[])
{
FormatImpl format;
format.Format(L"%t %m %i %l");
return 0;
}
在检查 Visual Studio 2010 时,函数 void __cdecl ParseFormat(LPCWSTR format);
作为 <Bad Ptr>
的参数变得无效。
我的问题是,如果我使用 GetProcAddress
或 LoadLibrary
来调用调用任何方法的 .dll 文件,那么我是否应该合法地传递除 int、double、对请求的方法进行了多长时间?
你的代码有一个主要问题:ParseFormat
是 不是 一个接受 LPWSTR 并返回 void 的函数,而是一个 class FormatLog
。不同之处在于,对于实例方法,您有一个隐藏的 this
参数。
如果您可以控制第一个项目,恕我直言,最简单的方法就是使用静态方法摆脱隐藏参数:
class __declspec(dllexport) FormatLog
{
public:
static void __cdecl ParseFormat(LPCWSTR);
};
如果您无法控制第一个项目,FORMAT
的正确类型将是指向成员的指针。不幸的是,我永远找不到将 GetProcAddress
的结果转换为指向成员的指针的方法。希望你知道你可以简单地获取成员函数的地址并直接调用它,前提是你添加隐藏的 this
作为第一个参数。代码将变为:
class FormatImpl
{
public:
typedef void (__cdecl *FORMAT) (FormatLog *l, LPCWSTR);
HINSTANCE hModule;
FORMAT Format;
FormatImpl()
{
hModule = LoadLibrary(L"FormatLog.dll");
if (hModule != NULL)
{
Format = (FORMAT) (void *) GetProcAddress(hModule,
"?ParseFormat@FormatLog@@QAAXPB_W@Z");
}
}
...
}
(在 FormatLog.exp
中得到损坏的名称后)你将像这样使用它:
int main(int argc, char* argv[])
{
FormatImpl format;
FormatLog l;
format.Format(&l, L"%t %m %i %l");
return 0;
}
无论如何,我通常认为损坏的名称应该是一个实现细节,如果我以后想通过 GetProcAddress
.[=24 手动导入它们,我只从 DLL 导出 extern "C"
函数=]
所以我的建议是在第一个项目中添加:
extern "C" {
__declspec(dllexport) void __cdecl doParseFormat(LPWSTR str) {
static FormatLog flog;
flog.ParseFormat(str);
}
}
现在你可以简单地写:
Format = (FORMAT) GetProcAddress(hModule, "doParseFormat");
我个人觉得比较干净,大家可以轻松使用。
我只是对将参数传递给不同项目的 C++ 函数感到困惑。
我有两种不同的方案,一种是DLL工程,另一种是Console工程。在第一个项目中,我有一段代码如下:
class __declspec(dllexport) FormatLog
{
public:
void __cdecl ParseFormat(LPCWSTR);
};
其余的代码在这里并不重要,而在第二个项目中我有包含以下代码的头文件:
class FormatImpl
{
public:
typedef void (__cdecl * FORMAT) (LPCWSTR);
HINSTANCE hModule;
FORMAT Format;
FormatImpl()
{
hModule = LoadLibrary(L"FormatLog.dll");
if (hModule != NULL)
{
Format = (FORMAT) GetProcAddress(hModule, "?ParseFormat@FormatLog@@XXXXXXXX@X");
}
}
~FormatImpl()
{
if (hModule != NULL)
{
FreeLibrary(hModule);
}
}
};
当我使用以下代码从主函数调用它时:
int main(int argc, char* argv[])
{
FormatImpl format;
format.Format(L"%t %m %i %l");
return 0;
}
在检查 Visual Studio 2010 时,函数 void __cdecl ParseFormat(LPCWSTR format);
作为 <Bad Ptr>
的参数变得无效。
我的问题是,如果我使用 GetProcAddress
或 LoadLibrary
来调用调用任何方法的 .dll 文件,那么我是否应该合法地传递除 int、double、对请求的方法进行了多长时间?
你的代码有一个主要问题:ParseFormat
是 不是 一个接受 LPWSTR 并返回 void 的函数,而是一个 class FormatLog
。不同之处在于,对于实例方法,您有一个隐藏的 this
参数。
如果您可以控制第一个项目,恕我直言,最简单的方法就是使用静态方法摆脱隐藏参数:
class __declspec(dllexport) FormatLog
{
public:
static void __cdecl ParseFormat(LPCWSTR);
};
如果您无法控制第一个项目,FORMAT
的正确类型将是指向成员的指针。不幸的是,我永远找不到将 GetProcAddress
的结果转换为指向成员的指针的方法。希望你知道你可以简单地获取成员函数的地址并直接调用它,前提是你添加隐藏的 this
作为第一个参数。代码将变为:
class FormatImpl
{
public:
typedef void (__cdecl *FORMAT) (FormatLog *l, LPCWSTR);
HINSTANCE hModule;
FORMAT Format;
FormatImpl()
{
hModule = LoadLibrary(L"FormatLog.dll");
if (hModule != NULL)
{
Format = (FORMAT) (void *) GetProcAddress(hModule,
"?ParseFormat@FormatLog@@QAAXPB_W@Z");
}
}
...
}
(在 FormatLog.exp
中得到损坏的名称后)你将像这样使用它:
int main(int argc, char* argv[])
{
FormatImpl format;
FormatLog l;
format.Format(&l, L"%t %m %i %l");
return 0;
}
无论如何,我通常认为损坏的名称应该是一个实现细节,如果我以后想通过 GetProcAddress
.[=24 手动导入它们,我只从 DLL 导出 extern "C"
函数=]
所以我的建议是在第一个项目中添加:
extern "C" {
__declspec(dllexport) void __cdecl doParseFormat(LPWSTR str) {
static FormatLog flog;
flog.ParseFormat(str);
}
}
现在你可以简单地写:
Format = (FORMAT) GetProcAddress(hModule, "doParseFormat");
我个人觉得比较干净,大家可以轻松使用。