【问题标题】:External Exception E0434352 on calling a C++/CLI Wrapper调用 C++/CLI 包装器时出现外部异常 E0434352
【发布时间】:2020-07-12 15:34:08
【问题描述】:

以下解决方案创建库“YahooAPI.dll”和“YahooAPIWrapper.dll”。 (原始项目在这里找到:http://pragmateek.com/using-c-from-native-c-with-the-help-of-ccli-v2/

我从第 3 方应用程序调用“YahooAPIWrapper.dll”,结果如下:

  • 函数“Foo”返回预期数据没有问题(它不调用 YahooAPI.dll)。
  • 函数“GetRevision”通过函数“GetRevisionUtil”调用“YahooAPI.dll”两次;每次调用都显示没有错误的 msgbox。但是,在显示第二个 msgbox 后,会出现一个弹出窗口,显示:External Exception E0434352

为了解决问题,我添加了 c++ 控制台应用程序。

请看下面代码中的cmets。

YahooAPI.dll:

// YahooAPI.cs

using System;
using System.Windows.Forms;

public class YahooAPI
{
    public string GetRevisionUtil(string rev)
    {
        MessageBox.Show("CurrentRev: " + rev);
        return "rev_" + rev ;
    }
}

YahooAPIWrapper.dll 头文件:

// YahooAPIWrapper.h

#pragma once

#define DLL_EXP extern "C" __declspec(dllexport)
DLL_EXP void GetRevision(char* data_in, char *data_out);
DLL_EXP void Foo(char* data_in, char *data_out);

class YahooAPIWrapperPrivate;
class __declspec(dllexport) YahooAPIWrapper
{
private:  YahooAPIWrapperPrivate* _private;

public:
    YahooAPIWrapper();
    ~YahooAPIWrapper();

    const char* GetRevisionFunc(const char* rev);
};

请看函数中的cmets:GetRevision

// YahooAPIWrapper.cpp

#include "stdafx.h"
#include <msclr\auto_gcroot.h>
#include <string>
#using "YahooAPI.dll"

#include <msclr\auto_gcroot.h>
#include "YahooAPIWrapper.h"

using namespace System::Runtime::InteropServices; // Marshal

DLL_EXP void GetRevision(char* data_in, char *data_out)
{
    YahooAPIWrapper wrp;
    const char* c = wrp.GetRevisionFunc(data_in);  // 1st messagebox shows
    const char* d = wrp.GetRevisionFunc(c);   // 2nd messagebox shows

    strcpy_s(data_out,100, d);  // << HERE <<  3rd party app throws 'external exception E0434352 '
                          // the console app throws the error 'Unhandled exception...'
}

const char* YahooAPIWrapper::GetRevisionFunc(const char* rev)
{
    System::String^ managedCapi = _private->yahooAPI->GetRevisionUtil(gcnew System::String(rev));
    return (const char*)Marshal::StringToHGlobalAnsi(managedCapi).ToPointer();
}

DLL_EXP void Foo(char* data_in, char *data_out)
{
    int a_size = int(strlen(data_in)); 
    std::string s_a = convertToString(data_in, a_size);
    strcpy_s(data_out,100, s_a.c_str());
}

std::string convertToString(char* a, int size)
{
    int i;
    std::string s = "";
    for (i = 0; i < size; i++) {
        s = s + a[i];
    }
    return s;
}

class YahooAPIWrapperPrivate
{
    public: msclr::auto_gcroot<YahooAPI^> yahooAPI;
};

YahooAPIWrapper::YahooAPIWrapper()
{
    _private = new YahooAPIWrapperPrivate();
    _private->yahooAPI = gcnew YahooAPI();
}

YahooAPIWrapper::~YahooAPIWrapper()
{
    delete _private;
}

控制台测试应用:

// Test.cpp 

#include <iostream>
#include <stdio.h>

#include "YahooAPIWrapper.h"

int main()
{
    YahooAPIWrapper yahoo;

    char* a = "aaaa";
    char* b = "bbbb";

    const char* c = yahoo.GetRevisionFunc(b); // messagebox shows
    std::cout << c << std::endl;

    GetRevision(a, b); // 1st & 2nd msgbox shows - then error: "unhandled exception..."
    std::cout << a << std::endl;
    std::cout << b << std::endl;

    return 0;
}

编辑:“控制台应用程序”错误已解决。 (上述错误全文: Test.exe 中 0x0f3c2fdd 处未处理的异常:0xC0000005:访问冲突写入位置 0x00da7830。)


编辑: 上述项目已缩减以下内容(参见 cmets) - 但仍然看到“外部异常 E0434352”:

namespace Publics {
    public class YahooAPI{
        public static void GetRevisionUtil() {
            string rev = "test";
            MessageBox.Show("CurrentRev: " + rev);
            //return "rev_" + rev;
        }
    }
}
// YahooAPIWrapper.h
#pragma once
#define DLL_EXP extern "C" __declspec(dllexport)
DLL_EXP void GetRevision(char* data_in, char *data_out);
DLL_EXP void Foo(char* data_in, char *data_out);
#include "stdafx.h"
#include <windows.h>
#include <msclr\auto_gcroot.h>
#include <string>

#using YahooAPI.dll"
#include "YahooAPIWrapper.h"

using namespace System::Runtime::InteropServices; // Marshal

DLL_EXP void GetRevision(char* data_in, char *data_out) 
// this function builds & works fine with console 
// however, immediately throws error (External Exception E0434352) when called by 3rd party app 
// - does not even make it to MessageBox.
{
    MessageBox(NULL, TEXT("msg1"), TEXT("Test"), MB_OK);

    Publics::YahooAPI::GetRevisionUtil();

    // Publics::YahooAPI^ obj = gcnew Publics::YahooAPI;
    // obj->GetRevisionUtil();

    strcpy(data_out,  data_in);
}

编辑: 使用 WinDbg 帮助我继续努力解决此错误 - 每: https://stackoverflow.com/a/6245146/3818364

在此处找到实际使用 WinDbg 的帮助: https://netmatze.wordpress.com/2012/08/24/using-windbg-exe-and-sos-dll-to-debug-a-net-4-0-application/

下面是 WinDbg 命令窗口中的 sn-p。
请注意以下命令的使用:
.load C:\Windows\Microsoft.NET\Framework\v4.0.30319\sos.dll
!threads

ntdll!DbgBreakPoint:
772c2790 cc              int     3
0:014> .load C:\Windows\Microsoft.NET\Framework\v4.0.30319\sos.dll
0:014> g
(9b3c.a350): C++ EH exception - code e06d7363 (first chance)
(9b3c.a350): C++ EH exception - code e06d7363 (first chance)
(9b3c.a350): C++ EH exception - code e06d7363 (first chance)
(9b3c.a350): CLR exception - code e0434352 (first chance)
(9b3c.a350): C++ EH exception - code e06d7363 (first chance)
(9b3c.87d8): Break instruction exception - code 80000003 (first chance)
eax=00353000 ebx=00000000 ecx=772fb3b0 edx=772fb3b0 esi=772fb3b0 edi=772fb3b0
eip=772c2790 esp=0e9eff44 ebp=0e9eff70 iopl=0         nv up ei pl zr na pe nc
cs=0023  ss=002b  ds=002b  es=002b  fs=0053  gs=002b             efl=00000246
ntdll!DbgBreakPoint:
772c2790 cc              int     3
0:014> !threads
ThreadCount:      2
UnstartedThread:  0
BackgroundThread: 2
PendingThread:    0
DeadThread:       0
Hosted Runtime:   no
                                                                         Lock  
       ID OSID ThreadOBJ    State GC Mode     GC Alloc Context  Domain   Count Apt Exception
   0    1 a350 0299d1b8     20220 Preemptive  0BFC41D4:00000000 04f22fd8 0     STA System.IO.FileNotFoundException 0bfc2768
  13    2 9b08 04f369c8     21220 Preemptive  00000000:00000000 04f22fd8 0     Ukn (Finalizer) 
0:014> !PrintException /d 0bfc2768
Exception object: 0bfc2768
Exception type:   System.IO.FileNotFoundException
Message:          Could not load file or assembly 'YahooAPI.dll, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null' or one of its dependencies. The system cannot find the file specified.
InnerException:   <none>

正如您在上面的窗口中看到的,我能够将原始错误“外部异常 E0434352”解决为“C++ EH 异常 - 代码 e06d7363”。最后能够将这个错误解决为平凡的:“System.IO.FileNotFoundException”。我的 YahooAPIWrapper.dll 找不到我的(托管)YahooAPI.dll - 即使它们都在同一个文件夹中。

底线:我的第 3 方应用程序具有配置功能,供用户浏览和选择其 Win32 dll 的文件夹。

我的错误是假设托管 DLL (YahooAPI.dll) 的正确位置与非托管 (YahooAPIWrapper.dll) 位于同一文件夹中。

只需将我的托管 DLL (YahooAPI.dll) 复制到第 3 方 .Exe 所在的文件夹即可解决该错误。中提琴!

【问题讨论】:

  • 现代 C++ 要求您使用const char* b = "bbbb";。优点是现在 strcpy_s() 调用必须失败的原因变得显而易见。
  • 感谢@HansPassant。我的第 3 方应用程序期望具有以下结构的函数: extern "C" DLL_EXP void My_Function(char* data_in, char *data_out);有没有比 strcpy_s 更好的函数来填充“data_out”?
  • @HansPassant - 我已经修改了我的方案(参见上面的编辑)以符合您的示例:stackoverflow.com/questions/17127825/c-sharp-unmanaged-exports/… 同样,代码在 C++ 控制台应用程序中工作,但是,我仍然看到烦人的:外部异常 E0434352。有什么想法吗?

标签: c# c++ c++-cli windbg


【解决方案1】:

使用 WinDbg 使我能够将通用的“外部异常 E0434352”错误解决为更有帮助的:“System.IO.FileNotFoundException”。请参阅我上次编辑的链接。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多