我正在使用C ++ MFC插件dll,它在运行时从现成的应用程序自动启动。我需要修改插件以支持与基于.NET的C#应用程序的双向通信。
我可以访问插件源代码,但我无法将C ++项目更改为使用/ clr。我从现成的应用程序中收到运行时错误:
' r6033尝试在本机代码初始化期间使用此程序集中的msil代码'
我曾试图使用" #pragma unmanaged"围绕Main方法没有运气。所以我决定走COM路线。
我已经成功创建了一个基于COM的C#dll,其中包含一个UI和实现的方法,我可以从C ++调用它。这让我有一个方向。我需要实现一种从C#应用程序调用C ++插件的方法。我开始沿着事件的道路前进。我在C#中创建了一个事件,它是在新的UI的C#端引发的,但是我无法弄清楚如何在C ++端创建和挂钩事件。任何帮助将不胜感激。
这是C#COM代码:
using System;
using System.Runtime.InteropServices;
using System.Windows.Forms;
using System.IO;
namespace MyInterop
{
[Guid("03AD5D2D-2AFD-439f-8713-A4EC0705B4D9")]
public interface IMyDotNetInterface
{
void ShowCOMDialog();
}
[InterfaceType(ComInterfaceType.InterfaceIsIDispatch)]
[Guid("63058ba6-5675-43d6-b38b-fd261fe64950")]
public interface IIntelliWaveEvents
{
[DispId(1)]
void CallIWave(string a_IWaveCommand);
}
[ClassInterface(ClassInterfaceType.None)]
[ComSourceInterfaces(typeof(IIntelliWaveEvents))]
[Guid("0490E147-F2D2-4909-A4B8-3533D2F264D0")]
public class MyDotNetClass : IMyDotNetInterface
{
public IIntelliWaveEvents callbackObject;
// Need a public default constructor for COM Interop.
public MyDotNetClass()
{ }
public void ShowCOMDialog()
{
MainForm frm = new MainForm()
{
StartPosition = FormStartPosition.CenterScreen,
TopMost = true
};
frm.CallIWave += new MainForm.CallIWaveEventHandler(frm_CallIWave);
frm.Show();
}
void frm_CallIWave(object sender, Events.IWaveEvents.CallIWaveEventArgs e)
{
string filename = @"C:\Companies\ComEvent.txt";
File.WriteAllText(filename, "COM Event Called at " + DateTime.Now);
//Pass the event to c++
if (callbackObject != null)
{
callbackObject.CallIWave(e.Message);
}
}
}
}
这是WaveDLL_PAI.cpp代码的接口:
#include "stdafx.h"
#include "WaveDLL_PAI.h"
#include "IUserPrograms1.h"
using namespace std;
#import "C:\Program Files\SampleCOM\com.MyInterop.tlb" named_guids raw_interfaces_only
using namespace MyInterop;
//------------------------------------------------------------------------
// This function must exist in all PlugIn(s).
// It creates an instance of the API class and returns a pointer to it.
HRESULT CreateInstance(void **p)
{
*p = new CWaveDLL_PAI();
return (*p != NULL);
}
//---------------------------------------------------------------------------------------------------
// Initialize native variables here
CWaveDLL_PAI::CWaveDLL_PAI() : CWaveDLL_BaseI()
{
}
//---------------------------------------------------------------------------------------------------
// deallocate any memory here
CWaveDLL_PAI::~CWaveDLL_PAI()
{
Release();
}
//---------------------------------------------------------------------------------------------------
// This function releases any memory allocated for this class
ULONG CWaveDLL_PAI::Release()
{
return 0;
}
//---------------------------------------------------------------------------------------------------
// This function must be used to create the class including memory allocation.
// Allocate memory or objects here only.
// Do not display any window or dialog here
ULONG CWaveDLL_PAI::Create(CWnd *pParent, void *a, void *b, void *c)
{
CoInitialize(NULL); //Initialize all COM Components
MyInterop::IMyDotNetInterfacePtr pDotNetCOMPtr;
HRESULT hRes = pDotNetCOMPtr.CreateInstance(MyInterop::CLSID_MyDotNetClass);
if (hRes == S_OK)
{
BSTR str;
pDotNetCOMPtr->ShowCOMDialog(); //call .NET COM exported function ShowDialog ()
}
CoUninitialize(); //DeInitialize all COM Components
return true;
}
//---------------------------------------------------------------------------------------------------
// This function gives the PlugIn access to data and controls
// This function must be defined and have the code listed below.
long CWaveDLL_PAI::SetData(CUserControl *ctrl, SIntelliWaveDataExt *data, LPCTSTR path)
{
CWaveDLL_BaseI::SetData(ctrl,data,path);
return true;
}
这是WaveDLL_PAI.h接口代码:
#include "WaveDLL_BaseI.h"
class AFX_EXT_CLASS CWaveDLL_PAI : public CWaveDLL_BaseI
{
public:
int MyVariable;
CWaveDLL_PAI();
~CWaveDLL_PAI();
int MyFunction(int hello = 0);
ULONG Release();
ULONG Create(CWnd *pParent=0, void *a = 0, void *b = 0, void *c = 0);
long SetData(CUserControl *ctrl, SIntelliWaveDataExt *data, LPCTSTR path = 0);
long Execute(LPCTSTR cmd, void *a = 0, void *b = 0, void *c = 0);
};
这是WaveDLL_PA.cpp代码:
#include "stdafx.h"
#include <afxdllx.h>
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
HINSTANCE hInstanceOptic01;
static AFX_EXTENSION_MODULE WaveDLL_PADLL = { NULL, NULL };
extern "C" int APIENTRY
DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved)
{
// Remove this if you use lpReserved
UNREFERENCED_PARAMETER(lpReserved);
hInstanceOptic01 = hInstance;
if (dwReason == DLL_PROCESS_ATTACH)
{
TRACE0("WaveDLL_PA.DLL Initializing!\n");
// Extension DLL one-time initialization
if (!AfxInitExtensionModule(WaveDLL_PADLL, hInstance))
return 0;
// Insert this DLL into the resource chain
// NOTE: If this Extension DLL is being implicitly linked to by
// an MFC Regular DLL (such as an ActiveX Control)
// instead of an MFC application, then you will want to
// remove this line from DllMain and put it in a separate
// function exported from this Extension DLL. The Regular DLL
// that uses this Extension DLL should then explicitly call that
// function to initialize this Extension DLL. Otherwise,
// the CDynLinkLibrary object will not be attached to the
// Regular DLL's resource chain, and serious problems will
// result.
new CDynLinkLibrary(WaveDLL_PADLL);
}
else if (dwReason == DLL_PROCESS_DETACH)
{
TRACE0("WaveDLL_PA.DLL Terminating!\n");
// Terminate the library before destructors are called
AfxTermExtensionModule(WaveDLL_PADLL);
}
return 1; // ok
}