Sec*_*ret 1 dll pinvoke cdecl dllexport dumpbin
我在VS中创建了新的Win32项目,并为此目的选择了动态库(*.dll).
我在主文件中定义了一些导出函数:
__declspec(dllexport)
int TestCall(void)
{
int value = 4 / 2;
std::cout << typeid(value).name() << std::endl;
return value;
}
__declspec(dllexport)
void SwapMe(int *first, int *second)
{
int tmp = *first;
*first = *second;
*second = tmp;
}
Run Code Online (Sandbox Code Playgroud)
当我看到dumpin/exports时,我得到了:
ordinal hint RVA name
1 0 00001010 ?SwapMe@@YAXPEAH0@Z
2 1 00001270 ?TestCall@@YAHXZ
Run Code Online (Sandbox Code Playgroud)
我正在调用C#这样的版本:
[DllImport(@"lib1.dll", EntryPoint = "?TestCall@@YAHXZ",
CallingConvention = CallingConvention.Cdecl)]
static extern int TestCall();
Run Code Online (Sandbox Code Playgroud)
这不是使用导出方法的正确形式.我在C++ DLL项目中为导出方法生成这样的名称失败了吗?
这是正常的,C++编译器将名称修饰应用于函数.C++语言支持函数重载,就像C#一样.所以你可以写一个Foo(int)和一个Foo(double)函数.显然,它们不能同时作为名为"Foo"的函数导出,客户端代码不知道要调用哪一个.因此额外的字符对名称进行编码,以使其对于重载是唯一的.
您可以通过声明函数来关闭它extern "C",C语言不支持重载,因此不需要相同类型的装饰.
但如果不这样做,实际上会更好.因为它也是捕捉错误的绝佳方式.就像更改C++代码中的函数声明但忘记修改C#代码中的pinvoke声明一样.现在,您将可以轻松诊断"未找到Entrypoint"异常,而不是非描述性且非常难以诊断AccessViolationException.这不一定要在C++代码中引发,堆栈不平衡也会导致C#代码崩溃.查找装饰名称有点痛苦,但通过要求链接器创建映射文件(/ MAP选项)来改进它.
| 归档时间: |
|
| 查看次数: |
1751 次 |
| 最近记录: |