非托管C ++(无CLR)与托管C#

时间:2016-03-03 20:28:13

标签: c# c++ .net mfc

我正在使用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
}

0 个答案:

没有答案