Reputation: 523
The below solution creates the libraries 'YahooAPI.dll' & 'YahooAPIWrapper.dll'. (original project found here: http://pragmateek.com/using-c-from-native-c-with-the-help-of-ccli-v2/)
From a 3rd party application I call 'YahooAPIWrapper.dll' with the following results:
For trouble-shooting I added the c++ console app.
Please see the comments in the below code.
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 header:
// 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);
};
Please see the comments in the function: 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;
}
Console test app:
// 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;
}
EDIT: the 'console app' error is resolved. (Full text of the above error: Unhandled exception at 0x0f3c2fdd in Test.exe: 0xC0000005: Access violation writing location 0x00da7830.)
EDIT: the above project has been pared down the following (see comments) - but still seeing 'External Exception 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);
}
EDIT: My continued efforts to resolve this error were helped by using WinDbg - per: https://stackoverflow.com/a/6245146/3818364
Help in actually using WinDbg was found here: https://netmatze.wordpress.com/2012/08/24/using-windbg-exe-and-sos-dll-to-debug-a-net-4-0-application/
Below is a snippet from the WinDbg command window.
Note the use of the following commands:
.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>
As you can see in the above window, I was able to resolve the original error 'External Exception E0434352' down to a 'C++ EH exception - code e06d7363'. And finally was able to resolve this error to the mundane: "System.IO.FileNotFoundException". My YahooAPIWrapper.dll could not find my (managed) YahooAPI.dll - even though they were both in the same folder.
Bottome line: my 3rd party app has a configuration function for the user to browse and select the folder for their Win32 dll.
My mistake was assuming that the correct location for the managed DLL (YahooAPI.dll) was to be in the same folder as the unmanaged (YahooAPIWrapper.dll).
The error was resolved by simply copying my managed DLL (YahooAPI.dll) to the folder where the 3rd party .Exe resides. Viola!
Upvotes: 2
Views: 3371
Reputation: 523
Using WinDbg allowed me to resolve the generic 'External Exception E0434352' error down to the more helpful: "System.IO.FileNotFoundException". Please see my last edit for links.
Upvotes: 2