zoukankan      html  css  js  c++  java
  • native C++ 动态调用.NET DLL

    关于这个问题找了好多地方,都只有第二种解决办法,可是我要返回一个字符串,没办法,继续找,最后还是在http://blogs.msdn.com/b/msdnforum/archive/2010/07/09/use-clr4-hosting-api-to-invoke-net-assembly-from-native-c.aspx找到了解决的办法,这里记下来备忘。

    转发下范例包:http://files.cnblogs.com/files/maintell/Cpp_app_hosts_CLR_4_and_invokes_.NET_assembly_%28CppHostCLR%29.zip

    第一种可以返回一个任意变量或者对象,第二种简单点,只能返回整型,具体看代码:

      1 //
      2 //   FUNCTION: RuntimeHostV4Demo1(PCWSTR, PCWSTR)
      3 //
      4 //   PURPOSE: The function demonstrates using .NET Framework 4.0 Hosting 
      5 //   Interfaces to host a .NET runtime, and use the ICorRuntimeHost interface
      6 //   that was provided in .NET v1.x to load a .NET assembly and invoke its 
      7 //   type. 
      8 //   
      9 //   If the .NET runtime specified by the pszVersion parameter cannot be 
     10 //   loaded into the current process, the function prints ".NET runtime <the 
     11 //   runtime version> cannot be loaded", and return.
     12 //   
     13 //   If the .NET runtime is successfully loaded, the function loads the 
     14 //   assembly identified by the pszAssemblyName parameter. Next, the function 
     15 //   instantiates the class (pszClassName) in the assembly, calls its 
     16 //   ToString() member method, and print the result. Last, the demo invokes 
     17 //   the public static function 'int GetStringLength(string str)' of the class 
     18 //   and print the result too.
     19 //
     20 //   PARAMETERS:
     21 //   * pszVersion - The desired DOTNETFX version, in the format “vX.X.XXXXX”. 
     22 //     The parameter must not be NULL. It’s important to note that this 
     23 //     parameter should match exactly the directory names for each version of
     24 //     the framework, under C:WindowsMicrosoft.NETFramework[64]. The 
     25 //     current possible values are "v1.0.3705", "v1.1.4322", "v2.0.50727" and 
     26 //     "v4.0.30319". Also, note that the “v” prefix is mandatory.
     27 //   * pszAssemblyName - The display name of the assembly to be loaded, such 
     28 //     as "CSClassLibrary". The ".DLL" file extension is not appended.
     29 //   * pszClassName - The name of the Type that defines the method to invoke.
     30 //
     31 //   RETURN VALUE: HRESULT of the demo.
     32 //
     33 HRESULT RuntimeHostV4Demo1(PCWSTR pszVersion, PCWSTR pszAssemblyName, 
     34     PCWSTR pszClassName)
     35 {
     36     HRESULT hr;
     37 
     38     ICLRMetaHost *pMetaHost = NULL;
     39     ICLRRuntimeInfo *pRuntimeInfo = NULL;
     40 
     41     // ICorRuntimeHost and ICLRRuntimeHost are the two CLR hosting interfaces
     42     // supported by CLR 4.0. Here we demo the ICorRuntimeHost interface that 
     43     // was provided in .NET v1.x, and is compatible with all .NET Frameworks. 
     44     ICorRuntimeHost *pCorRuntimeHost = NULL;
     45 
     46     IUnknownPtr spAppDomainThunk = NULL;
     47     _AppDomainPtr spDefaultAppDomain = NULL;
     48 
     49     // The .NET assembly to load.
     50     bstr_t bstrAssemblyName(pszAssemblyName);
     51     _AssemblyPtr spAssembly = NULL;
     52 
     53     // The .NET class to instantiate.
     54     bstr_t bstrClassName(pszClassName);
     55     _TypePtr spType = NULL;
     56     variant_t vtObject;
     57     variant_t vtEmpty;
     58 
     59     // The static method in the .NET class to invoke.
     60     bstr_t bstrStaticMethodName(L"GetStringLength");
     61     SAFEARRAY *psaStaticMethodArgs = NULL;
     62     variant_t vtStringArg(L"HelloWorld");
     63     variant_t vtLengthRet;
     64 
     65     // The instance method in the .NET class to invoke.
     66     bstr_t bstrMethodName(L"ToString");
     67     SAFEARRAY *psaMethodArgs = NULL;
     68     variant_t vtStringRet;
     69 
     70     // 
     71     // Load and start the .NET runtime.
     72     // 
     73 
     74     wprintf(L"Load and start the .NET runtime %s 
    ", pszVersion);
     75 
     76     hr = CLRCreateInstance(CLSID_CLRMetaHost, IID_PPV_ARGS(&pMetaHost));
     77     if (FAILED(hr))
     78     {
     79         wprintf(L"CLRCreateInstance failed w/hr 0x%08lx
    ", hr);
     80         goto Cleanup;
     81     }
     82 
     83     // Get the ICLRRuntimeInfo corresponding to a particular CLR version. It 
     84     // supersedes CorBindToRuntimeEx with STARTUP_LOADER_SAFEMODE.
     85     hr = pMetaHost->GetRuntime(pszVersion, IID_PPV_ARGS(&pRuntimeInfo));
     86     if (FAILED(hr))
     87     {
     88         wprintf(L"ICLRMetaHost::GetRuntime failed w/hr 0x%08lx
    ", hr);
     89         goto Cleanup;
     90     }
     91 
     92     // Check if the specified runtime can be loaded into the process. This 
     93     // method will take into account other runtimes that may already be 
     94     // loaded into the process and set pbLoadable to TRUE if this runtime can 
     95     // be loaded in an in-process side-by-side fashion. 
     96     BOOL fLoadable;
     97     hr = pRuntimeInfo->IsLoadable(&fLoadable);
     98     if (FAILED(hr))
     99     {
    100         wprintf(L"ICLRRuntimeInfo::IsLoadable failed w/hr 0x%08lx
    ", hr);
    101         goto Cleanup;
    102     }
    103 
    104     if (!fLoadable)
    105     {
    106         wprintf(L".NET runtime %s cannot be loaded
    ", pszVersion);
    107         goto Cleanup;
    108     }
    109 
    110     // Load the CLR into the current process and return a runtime interface 
    111     // pointer. ICorRuntimeHost and ICLRRuntimeHost are the two CLR hosting  
    112     // interfaces supported by CLR 4.0. Here we demo the ICorRuntimeHost 
    113     // interface that was provided in .NET v1.x, and is compatible with all 
    114     // .NET Frameworks. 
    115     hr = pRuntimeInfo->GetInterface(CLSID_CorRuntimeHost, 
    116         IID_PPV_ARGS(&pCorRuntimeHost));
    117     if (FAILED(hr))
    118     {
    119         wprintf(L"ICLRRuntimeInfo::GetInterface failed w/hr 0x%08lx
    ", hr);
    120         goto Cleanup;
    121     }
    122 
    123     // Start the CLR.
    124     hr = pCorRuntimeHost->Start();
    125     if (FAILED(hr))
    126     {
    127         wprintf(L"CLR failed to start w/hr 0x%08lx
    ", hr);
    128         goto Cleanup;
    129     }
    130 
    131     // 
    132     // Load the NET assembly. Call the static method GetStringLength of the 
    133     // class CSSimpleObject. Instantiate the class CSSimpleObject and call 
    134     // its instance method ToString.
    135     // 
    136 
    137     // The following C++ code does the same thing as this C# code:
    138     // 
    139     //   Assembly assembly = AppDomain.CurrentDomain.Load(pszAssemblyName);
    140     //   object length = type.InvokeMember("GetStringLength", 
    141     //       BindingFlags.InvokeMethod | BindingFlags.Static | 
    142     //       BindingFlags.Public, null, null, new object[] { "HelloWorld" });
    143     //   object obj = assembly.CreateInstance("CSClassLibrary.CSSimpleObject");
    144     //   object str = type.InvokeMember("ToString", 
    145     //       BindingFlags.InvokeMethod | BindingFlags.Instance | 
    146     //       BindingFlags.Public, null, obj, new object[] { });
    147 
    148     // Get a pointer to the default AppDomain in the CLR.
    149     hr = pCorRuntimeHost->GetDefaultDomain(&spAppDomainThunk);
    150     if (FAILED(hr))
    151     {
    152         wprintf(L"ICorRuntimeHost::GetDefaultDomain failed w/hr 0x%08lx
    ", hr);
    153         goto Cleanup;
    154     }
    155 
    156     hr = spAppDomainThunk->QueryInterface(IID_PPV_ARGS(&spDefaultAppDomain));
    157     if (FAILED(hr))
    158     {
    159         wprintf(L"Failed to get default AppDomain w/hr 0x%08lx
    ", hr);
    160         goto Cleanup;
    161     }
    162 
    163     // Load the .NET assembly.
    164     wprintf(L"Load the assembly %s
    ", pszAssemblyName);
    165     hr = spDefaultAppDomain->Load_2(bstrAssemblyName, &spAssembly);
    166     if (FAILED(hr))
    167     {
    168         wprintf(L"Failed to load the assembly w/hr 0x%08lx
    ", hr);
    169         goto Cleanup;
    170     }
    171 
    172     // Get the Type of CSSimpleObject.
    173     hr = spAssembly->GetType_2(bstrClassName, &spType);
    174     if (FAILED(hr))
    175     {
    176         wprintf(L"Failed to get the Type interface w/hr 0x%08lx
    ", hr);
    177         goto Cleanup;
    178     }
    179 
    180     // Call the static method of the class: 
    181     //   public static int GetStringLength(string str);
    182 
    183     // Create a safe array to contain the arguments of the method. The safe 
    184     // array must be created with vt = VT_VARIANT because .NET reflection 
    185     // expects an array of Object - VT_VARIANT. There is only one argument, 
    186     // so cElements = 1.
    187     psaStaticMethodArgs = SafeArrayCreateVector(VT_VARIANT, 0, 1);
    188     LONG index = 0;
    189     hr = SafeArrayPutElement(psaStaticMethodArgs, &index, &vtStringArg);
    190     if (FAILED(hr))
    191     {
    192         wprintf(L"SafeArrayPutElement failed w/hr 0x%08lx
    ", hr);
    193         goto Cleanup;
    194     }
    195 
    196     // Invoke the "GetStringLength" method from the Type interface.
    197     hr = spType->InvokeMember_3(bstrStaticMethodName, static_cast<BindingFlags>(
    198         BindingFlags_InvokeMethod | BindingFlags_Static | BindingFlags_Public), 
    199         NULL, vtEmpty, psaStaticMethodArgs, &vtLengthRet);
    200     if (FAILED(hr))
    201     {
    202         wprintf(L"Failed to invoke GetStringLength w/hr 0x%08lx
    ", hr);
    203         goto Cleanup;
    204     }
    205 
    206     // Print the call result of the static method.
    207     wprintf(L"Call %s.%s("%s") => %s
    ", 
    208         static_cast<PCWSTR>(bstrClassName), 
    209         static_cast<PCWSTR>(bstrStaticMethodName), 
    210         static_cast<PCWSTR>(vtStringArg.bstrVal), 
    211         vtLengthRet.lVal);
    212 
    213     // Instantiate the class.
    214     hr = spAssembly->CreateInstance(bstrClassName, &vtObject);
    215     if (FAILED(hr))
    216     {
    217         wprintf(L"Assembly::CreateInstance failed w/hr 0x%08lx
    ", hr);
    218         goto Cleanup;
    219     }
    220 
    221     // Call the instance method of the class.
    222     //   public string ToString();
    223 
    224     // Create a safe array to contain the arguments of the method.
    225     psaMethodArgs = SafeArrayCreateVector(VT_VARIANT, 0, 0);
    226 
    227     // Invoke the "ToString" method from the Type interface.
    228     hr = spType->InvokeMember_3(bstrMethodName, static_cast<BindingFlags>(
    229         BindingFlags_InvokeMethod | BindingFlags_Instance | BindingFlags_Public),
    230         NULL, vtObject, psaMethodArgs, &vtStringRet);
    231     if (FAILED(hr))
    232     {
    233         wprintf(L"Failed to invoke ToString w/hr 0x%08lx
    ", hr);
    234         goto Cleanup;
    235     }
    236 
    237     // Print the call result of the method.
    238     wprintf(L"Call %s.%s() => %s
    ", 
    239         static_cast<PCWSTR>(bstrClassName), 
    240         static_cast<PCWSTR>(bstrMethodName), 
    241         static_cast<PCWSTR>(vtStringRet.bstrVal));
    242 
    243 Cleanup:
    244 
    245     if (pMetaHost)
    246     {
    247         pMetaHost->Release();
    248         pMetaHost = NULL;
    249     }
    250     if (pRuntimeInfo)
    251     {
    252         pRuntimeInfo->Release();
    253         pRuntimeInfo = NULL;
    254     }
    255     if (pCorRuntimeHost)
    256     {
    257         // Please note that after a call to Stop, the CLR cannot be 
    258         // reinitialized into the same process. This step is usually not 
    259         // necessary. You can leave the .NET runtime loaded in your process.
    260         //wprintf(L"Stop the .NET runtime
    ");
    261         //pCorRuntimeHost->Stop();
    262 
    263         pCorRuntimeHost->Release();
    264         pCorRuntimeHost = NULL;
    265     }
    266 
    267     if (psaStaticMethodArgs)
    268     {
    269         SafeArrayDestroy(psaStaticMethodArgs);
    270         psaStaticMethodArgs = NULL;
    271     }
    272     if (psaMethodArgs)
    273     {
    274         SafeArrayDestroy(psaMethodArgs);
    275         psaMethodArgs = NULL;
    276     }
    277 
    278     return hr;
    279 }

    第二种比较简单:

      1 //
      2 //   FUNCTION: RuntimeHostV4Demo2(PCWSTR, PCWSTR)
      3 //
      4 //   PURPOSE: The function demonstrates using .NET Framework 4.0 Hosting 
      5 //   Interfaces to host a .NET runtime, and use the ICLRRuntimeHost interface
      6 //   that was provided in .NET v2.0 to load a .NET assembly and invoke its 
      7 //   type. Because ICLRRuntimeHost is not compatible with .NET runtime v1.x, 
      8 //   the requested runtime must not be v1.x.
      9 //   
     10 //   If the .NET runtime specified by the pszVersion parameter cannot be 
     11 //   loaded into the current process, the function prints ".NET runtime <the 
     12 //   runtime version> cannot be loaded", and return.
     13 //   
     14 //   If the .NET runtime is successfully loaded, the function loads the 
     15 //   assembly identified by the pszAssemblyName parameter. Next, the function 
     16 //   invokes the public static function 'int GetStringLength(string str)' of 
     17 //   the class and print the result.
     18 //
     19 //   PARAMETERS:
     20 //   * pszVersion - The desired DOTNETFX version, in the format “vX.X.XXXXX”. 
     21 //     The parameter must not be NULL. It’s important to note that this 
     22 //     parameter should match exactly the directory names for each version of
     23 //     the framework, under C:WindowsMicrosoft.NETFramework[64]. Because 
     24 //     the ICLRRuntimeHost interface does not support the .NET v1.x runtimes, 
     25 //     the current possible values of the parameter are "v2.0.50727" and 
     26 //     "v4.0.30319". Also, note that the “v” prefix is mandatory.
     27 //   * pszAssemblyPath - The path to the Assembly to be loaded.
     28 //   * pszClassName - The name of the Type that defines the method to invoke.
     29 //
     30 //   RETURN VALUE: HRESULT of the demo.
     31 //
     32 HRESULT RuntimeHostV4Demo2(PCWSTR pszVersion, PCWSTR pszAssemblyPath, 
     33     PCWSTR pszClassName)
     34 {
     35     HRESULT hr;
     36 
     37     ICLRMetaHost *pMetaHost = NULL;
     38     ICLRRuntimeInfo *pRuntimeInfo = NULL;
     39 
     40     // ICorRuntimeHost and ICLRRuntimeHost are the two CLR hosting interfaces
     41     // supported by CLR 4.0. Here we demo the ICLRRuntimeHost interface that 
     42     // was provided in .NET v2.0 to support CLR 2.0 new features. 
     43     // ICLRRuntimeHost does not support loading the .NET v1.x runtimes.
     44     ICLRRuntimeHost *pClrRuntimeHost = NULL;
     45 
     46     // The static method in the .NET class to invoke.
     47     PCWSTR pszStaticMethodName = L"GetStringLength";
     48     PCWSTR pszStringArg = L"HelloWorld";
     49     DWORD dwLengthRet;
     50 
     51     // 
     52     // Load and start the .NET runtime.
     53     // 
     54 
     55     wprintf(L"Load and start the .NET runtime %s 
    ", pszVersion);
     56 
     57     hr = CLRCreateInstance(CLSID_CLRMetaHost, IID_PPV_ARGS(&pMetaHost));
     58     if (FAILED(hr))
     59     {
     60         wprintf(L"CLRCreateInstance failed w/hr 0x%08lx
    ", hr);
     61         goto Cleanup;
     62     }
     63 
     64     // Get the ICLRRuntimeInfo corresponding to a particular CLR version. It 
     65     // supersedes CorBindToRuntimeEx with STARTUP_LOADER_SAFEMODE.
     66     hr = pMetaHost->GetRuntime(pszVersion, IID_PPV_ARGS(&pRuntimeInfo));
     67     if (FAILED(hr))
     68     {
     69         wprintf(L"ICLRMetaHost::GetRuntime failed w/hr 0x%08lx
    ", hr);
     70         goto Cleanup;
     71     }
     72 
     73     // Check if the specified runtime can be loaded into the process. This 
     74     // method will take into account other runtimes that may already be 
     75     // loaded into the process and set pbLoadable to TRUE if this runtime can 
     76     // be loaded in an in-process side-by-side fashion. 
     77     BOOL fLoadable;
     78     hr = pRuntimeInfo->IsLoadable(&fLoadable);
     79     if (FAILED(hr))
     80     {
     81         wprintf(L"ICLRRuntimeInfo::IsLoadable failed w/hr 0x%08lx
    ", hr);
     82         goto Cleanup;
     83     }
     84 
     85     if (!fLoadable)
     86     {
     87         wprintf(L".NET runtime %s cannot be loaded
    ", pszVersion);
     88         goto Cleanup;
     89     }
     90 
     91     // Load the CLR into the current process and return a runtime interface 
     92     // pointer. ICorRuntimeHost and ICLRRuntimeHost are the two CLR hosting  
     93     // interfaces supported by CLR 4.0. Here we demo the ICLRRuntimeHost 
     94     // interface that was provided in .NET v2.0 to support CLR 2.0 new 
     95     // features. ICLRRuntimeHost does not support loading the .NET v1.x 
     96     // runtimes.
     97     hr = pRuntimeInfo->GetInterface(CLSID_CLRRuntimeHost, 
     98         IID_PPV_ARGS(&pClrRuntimeHost));
     99     if (FAILED(hr))
    100     {
    101         wprintf(L"ICLRRuntimeInfo::GetInterface failed w/hr 0x%08lx
    ", hr);
    102         goto Cleanup;
    103     }
    104 
    105     // Start the CLR.
    106     hr = pClrRuntimeHost->Start();
    107     if (FAILED(hr))
    108     {
    109         wprintf(L"CLR failed to start w/hr 0x%08lx
    ", hr);
    110         goto Cleanup;
    111     }
    112 
    113     // 
    114     // Load the NET assembly and call the static method GetStringLength of 
    115     // the type CSSimpleObject in the assembly.
    116     // 
    117 
    118     wprintf(L"Load the assembly %s
    ", pszAssemblyPath);
    119 
    120     // The invoked method of ExecuteInDefaultAppDomain must have the 
    121     // following signature: static int pwzMethodName (String pwzArgument)
    122     // where pwzMethodName represents the name of the invoked method, and 
    123     // pwzArgument represents the string value passed as a parameter to that 
    124     // method. If the HRESULT return value of ExecuteInDefaultAppDomain is 
    125     // set to S_OK, pReturnValue is set to the integer value returned by the 
    126     // invoked method. Otherwise, pReturnValue is not set.
    127     hr = pClrRuntimeHost->ExecuteInDefaultAppDomain(pszAssemblyPath, 
    128         pszClassName, pszStaticMethodName, pszStringArg, &dwLengthRet);
    129     if (FAILED(hr))
    130     {
    131         wprintf(L"Failed to call GetStringLength w/hr 0x%08lx
    ", hr);
    132         goto Cleanup;
    133     }
    134 
    135     // Print the call result of the static method.
    136     wprintf(L"Call %s.%s("%s") => %d
    ", pszClassName, pszStaticMethodName, 
    137         pszStringArg, dwLengthRet);
    138 
    139 Cleanup:
    140 
    141     if (pMetaHost)
    142     {
    143         pMetaHost->Release();
    144         pMetaHost = NULL;
    145     }
    146     if (pRuntimeInfo)
    147     {
    148         pRuntimeInfo->Release();
    149         pRuntimeInfo = NULL;
    150     }
    151     if (pClrRuntimeHost)
    152     {
    153         // Please note that after a call to Stop, the CLR cannot be 
    154         // reinitialized into the same process. This step is usually not 
    155         // necessary. You can leave the .NET runtime loaded in your process.
    156         //wprintf(L"Stop the .NET runtime
    ");
    157         //pClrRuntimeHost->Stop();
    158 
    159         pClrRuntimeHost->Release();
    160         pClrRuntimeHost = NULL;
    161     }
    162 
    163     return hr;
    164 }
    View Code
  • 相关阅读:
    apt局域网源搭建
    openstack 使用集锦
    nova-network创建初始化网络
    ubunt 基于deb 配置本地apt 源 分成仅本机使用,局域网使用2种
    使用HTML5监測站点性能
    写一个函数将传入的字符串转换成驼峰表示法
    简略的帧动画
    献给那些前端学习迷茫的人 -----前端开发必备的11项技能!!!
    排列组合(permutation)系列解题报告
    mysql 经常使用命令整理总结
  • 原文地址:https://www.cnblogs.com/maintell/p/5106160.html
Copyright © 2011-2022 走看看