您的位置:首页 > 编程语言 > C语言/C++

c++ 非托管程序调用c#托管程序l的实现操作方式

2017-07-28 00:18 609 查看
        最近,做产品开发,需要在非托管的c++程序调用c#的托管程序。经过试验,整理了一种简便方法,但该方法局限比较多,后面会推荐另外一个方式。现在先介绍该方法的操作步骤如下:

       1.创建c#的dll中接口的定义参看下面的示例。注意接口中的函数必须为静态的函数,输入参数只能有一个字符串类型,返回值必须为int,具体参看下面说明。

using System.IO;

using System.Xml;

using System.Data;

namespace CLRLib

{

    /// <summary>

    /// 此类为和c++交互的接口类,成员函数均为静态函数

    /// </summary>

    class cgCLRLibAccessAdapter

    {

        /// <summary>

        /// 测试

        /// </summary>

        /// <param name="szParam">标志参数</param>

        /// <returns>返回值</returns>
//  备注:接口函数只能为静态函数,返回值只能为Int,输入参数只能有一个字符串

        public static Int32 IsTest(String szParam)

        {

    int i= 2;

                return i;
}

     }

}

    2.定义了类cgCLRAccess用来操作访问c#类的函数。具体类的定义参看附件文件cgCLRAcess.h和cgCLRAcess.cpp。

文件cgCLRAcess.h:

#pragma once

#include "stdafx.h"

#include <MSCorEE.h>

//=========================================================================

//访问CLRDll的相关类

class cgCLRAccess

{

private:
CString m_szFileName;   //动态库文件全名
CString m_szClassName;  //c#类名称
ICLRRuntimeHost *m_pClrHost; //CLR运行时态宿主
CString m_szNetFrameVersion; //dll的目标FrameWork版本

public:
cgCLRAccess(CString fileName,CString className,CString netFrameVersion);
~cgCLRAccess();
//运行方法
int RunMethod(CString szMethodName,CString szParamString);

};

文件cgCLRAcess.cpp:

#include "StdAfx.h"

#include "cgCLRAccess.h"

#include <Windows.h>

#include <assert.h>

#include <Windows.h>

#include <MSCorEE.h>

using namespace std;

#pragma comment(lib,"mscoree.lib")

// ---------------------------------------------------------------

// 名称: cgCLRAccess

// 功能: 构造函数

// 变量: [in] fileName -- dll文件名

// [in] className -- 类名,包含命名空间

// [in] netFrameVersion -- NetFrame版本号

// 返回: 返回值int表示结果,-1,表示运行方法失败

// 编写: 张伟强,20170725

// ---------------------------------------------------------------

cgCLRAccess::cgCLRAccess(CString fileName,CString className,CString netFrameVersion)

{
m_szFileName=fileName;
m_szClassName=className;
m_szNetFrameVersion=netFrameVersion;
m_pClrHost =NULL;
//注意只能调用一次,第一个需要传递c#dll的.net framework版本号,缺省空为2.0
HRESULT hr = CorBindToRuntimeEx(m_szNetFrameVersion,
NULL,0,
CLSID_CLRRuntimeHost,
IID_ICLRRuntimeHost,
(PVOID*)&m_pClrHost);

if(hr != S_OK||hr != S_FAILED)
{
m_pClrHost = NULL;
return;
}
if(m_pClrHost)
{
hr=m_pClrHost->Start();
}

}

cgCLRAccess::~cgCLRAccess()

{
if(m_pClrHost != NULL)--只能加载一次
{
m_pClrHost->Stop();
m_pClrHost->Release();
}

}

// ---------------------------------------------------------------

// 名称: RunMethod

// 功能: 运行方法

// 变量: [in] szMethodName -- 方法名称

// [in] szParamString -- 方法参数

// 返回: 返回值int表示结果,-1,表示运行方法失败

// 编写: 张伟强,20170725

// ---------------------------------------------------------------

int cgCLRAccess::RunMethod(CString szMethodName,CString szParamString)

{
DWORD retVal=0;
//将dll加载到默认应用程序域中,并调用其中的方法
HRESULT hr = m_pClrHost->ExecuteInDefaultAppDomain(m_szFileName,m_szClassName,szMethodName,
szParamString,&retVal);
//后面增加错误处理
if(hr!=S_OK)
{
retVal = -1;
}
return retVal;

}

   3.c++调用的代码如下:
CString szParam=_T("test");
// 需要注意,这个类只能定义一次。_T("v4.0.30319")为c#依赖的.NetFrame版本号,如果传递错误,则会导致后面运行ExecuteInDefaultAppDomain出错,错误代码-2146234341或者FFFFFFFF8013101B。CLRLib.dll 为dll库的文件名,需要时要带路径
cgCLRAccess clrAccess(_T("CLRLib.dll"),_T("CLRLib.cgCLRLibAccessAdapter"),_T("v4.0.30319"));
int nRet =clrAccess.RunMethod(_T("IsTest"),szParam);

   按照以上操作,就完成了整个过程。以上,是我的学习过程遇到的问题和解决办法,记录下来防止自己忘记,同时也与大家分享,免走弯路。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息