C ++:显式DLL加载:非“extern C”的第一次机会异常功能 [英] C++: Explicit DLL Loading: First-chance Exception on non "extern C" functions

查看:213
本文介绍了C ++:显式DLL加载:非“extern C”的第一次机会异常功能的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

导入C ++函数时遇到麻烦。如果我将其声明为C函数,我可以成功导入它们。当显式加载时,如果任何函数缺少extern作为C装饰,我得到以下异常:

 第一次机会cpp.exe中的0x00000000异常:0xC0000005:访问冲突。 

DLL.h:

  externC__declspec(dllimport)int addC(int a,int b); 
__declspec(dllimport)int addCpp(int a,int b);

DLL.cpp:

  #includeDLL.h
int addC(int a,int b){
return a + b;
}
int addCpp(int a,int b){
return a + b;
}

main.cpp:

  #include..DLL / DLL.h
#include< stdio.h>
#include< windows.h>

int main(){
int a = 2;
int b = 1;
typedef int(* PFNaddC)(int,int);
typedef int(* PFNaddCpp)(int,int);

HMODULE hDLL = LoadLibrary(TEXT(../ Debug / DLL.dll));

if(hDLL!= NULL)
{
PFNaddC pfnAddC =(PFNaddC)GetProcAddress(hDLL,addC);
PFNaddCpp pfnAddCpp =(PFNaddCpp)GetProcAddress(hDLL,addCpp);
printf(a =%d,b =%d\\\
,a,b);
printf(pfnAddC:%d\\\
,pfnAddC(a,b));
printf(pfnAddCpp:%d\\\
,pfnAddCpp(a,b)); // EXCEPTION ON this LINE

}
getchar();
return 0;
}

如何导入c ++函数以进行动态加载?我发现以下代码通过引用* .lib来处理隐式加载,但我想了解动态加载。



提前谢谢。



更新:
bindump / exports

 code> 1 00011109?addCpp @@ YAHHH @ Z = @ ILT + 260(?addCpp @@ YAHHH @ Z)
2 00011136 addC = @ ILT + 305(_addC)

解决方案


  1. 创建转换结构
    found 这里

  2. 查看
    文件导出并显式复制
    c ++ mangle命名约定



    PFNaddCpp pfnAddCpp =(PFNaddCpp)GetProcAddress(hDLL,?addCpp @@ YAHHH @ Z);



解决方案

不可避免地,空指针上的访问冲突是beca使用 GetProcAddress()返回null错误。



问题是C ++的名称是由编译器调用,以适应各种C ++功能(命名空间,类和重载等)。因此,您的函数 addCpp()在生成的库中并未真正命名为 addCpp()。当您使用 externC声明函数时,您将放弃重载和将该函数放在命名空间中的选项,但作为回报,您将获得一个名称不为可以从C代码调用(不知道任何关于名称的变化)。



解决这个问题的一个选项是使用 .def 文件导出功能重命名导出的函数。有一篇文章,显式链接到DLL中的类 ,描述需要做什么。


I am having trouble importing my C++ functions. If I declare them as C functions I can successfully import them. When explicit loading, if any of the functions are missing the extern as C decoration I get a the following exception:

First-chance exception at 0x00000000 in cpp.exe: 0xC0000005: Access violation.

DLL.h:

extern "C" __declspec(dllimport) int addC(int a, int b);
__declspec(dllimport) int addCpp(int a, int b);

DLL.cpp:

#include "DLL.h"
int addC(int a, int b) {
    return a + b;
}
int addCpp(int a, int b) {
    return a + b;
}

main.cpp:

#include "..DLL/DLL.h"
#include <stdio.h>
#include <windows.h>

int main() {
    int a = 2;
    int b = 1;
    typedef int (*PFNaddC)(int,int);
    typedef int (*PFNaddCpp)(int,int);

    HMODULE hDLL = LoadLibrary(TEXT("../Debug/DLL.dll"));

    if (hDLL != NULL)
    {
        PFNaddC pfnAddC = (PFNaddC)GetProcAddress(hDLL, "addC");
        PFNaddCpp pfnAddCpp = (PFNaddCpp)GetProcAddress(hDLL, "addCpp");
        printf("a=%d, b=%d\n", a,b);
        printf("pfnAddC: %d\n", pfnAddC(a,b));
        printf("pfnAddCpp: %d\n", pfnAddCpp(a,b)); //EXCEPTION ON THIS LINE

    }
    getchar();
    return 0;
}

How can I import c++ functions for dynamic loading? I have found that the following code works with implicit loading by referencing the *.lib, but I would like to learn about dynamic loading.

Thank you to all in advance.

Update: bindump /exports

1 00011109 ?addCpp@@YAHHH@Z = @ILT+260(?addCpp@@YAHHH@Z)
2 00011136 addC = @ILT+305(_addC)

Solution:

  1. Create a conversion struct as found here
  2. Take a look at the file exports and copy explicitly the c++ mangle naming convention.

    PFNaddCpp pfnAddCpp = (PFNaddCpp)GetProcAddress(hDLL, "?addCpp@@YAHHH@Z");

解决方案

Inevitably, the access violation on the null pointer is because GetProcAddress() returns null on error.

The problem is that C++ names are mangled by the compiler to accommodate a variety of C++ features (namespaces, classes, and overloading, among other things). So, your function addCpp() is not really named addCpp() in the resulting library. When you declare the function with extern "C", you give up overloading and the option of putting the function in a namespace, but in return you get a function whose name is not mangled, and which you can call from C code (which doesn't know anything about name mangling.)

One option to get around this is to export the functions using a .def file to rename the exported functions. There's an article, Explicitly Linking to Classes in DLLs, that describes what is necessary to do this.

这篇关于C ++:显式DLL加载:非“extern C”的第一次机会异常功能的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆