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
第一种可以返回一个任意变量或者对象,第二种简单点,只能返回整型,具体看代码:
//
// FUNCTION: RuntimeHostV4Demo1(PCWSTR, PCWSTR)
//
// PURPOSE: The function demonstrates using .NET Framework 4.0 Hosting
// Interfaces to host a .NET runtime, and use the ICorRuntimeHost interface
// that was provided in .NET v1.x to load a .NET assembly and invoke its
// type.
//
// If the .NET runtime specified by the pszVersion parameter cannot be
// loaded into the current process, the function prints ".NET runtime <the
// runtime version> cannot be loaded", and return.
//
// If the .NET runtime is successfully loaded, the function loads the
// assembly identified by the pszAssemblyName parameter. Next, the function
// instantiates the class (pszClassName) in the assembly, calls its
// ToString() member method, and print the result. Last, the demo invokes
// the public static function 'int GetStringLength(string str)' of the class
// and print the result too.
//
// PARAMETERS:
// * pszVersion - The desired DOTNETFX version, in the format “vX.X.XXXXX”.
// The parameter must not be NULL. It’s important to note that this
// parameter should match exactly the directory names for each version of
// the framework, under C:\Windows\Microsoft.NET\Framework[64]. The
// current possible values are "v1.0.3705", "v1.1.4322", "v2.0.50727" and
// "v4.0.30319". Also, note that the “v” prefix is mandatory.
// * pszAssemblyName - The display name of the assembly to be loaded, such
// as "CSClassLibrary". The ".DLL" file extension is not appended.
// * pszClassName - The name of the Type that defines the method to invoke.
//
// RETURN VALUE: HRESULT of the demo.
//
HRESULT RuntimeHostV4Demo1(PCWSTR pszVersion, PCWSTR pszAssemblyName,
PCWSTR pszClassName)
{
HRESULT hr; ICLRMetaHost *pMetaHost = NULL;
ICLRRuntimeInfo *pRuntimeInfo = NULL; // ICorRuntimeHost and ICLRRuntimeHost are the two CLR hosting interfaces
// supported by CLR 4.0. Here we demo the ICorRuntimeHost interface that
// was provided in .NET v1.x, and is compatible with all .NET Frameworks.
ICorRuntimeHost *pCorRuntimeHost = NULL; IUnknownPtr spAppDomainThunk = NULL;
_AppDomainPtr spDefaultAppDomain = NULL; // The .NET assembly to load.
bstr_t bstrAssemblyName(pszAssemblyName);
_AssemblyPtr spAssembly = NULL; // The .NET class to instantiate.
bstr_t bstrClassName(pszClassName);
_TypePtr spType = NULL;
variant_t vtObject;
variant_t vtEmpty; // The static method in the .NET class to invoke.
bstr_t bstrStaticMethodName(L"GetStringLength");
SAFEARRAY *psaStaticMethodArgs = NULL;
variant_t vtStringArg(L"HelloWorld");
variant_t vtLengthRet; // The instance method in the .NET class to invoke.
bstr_t bstrMethodName(L"ToString");
SAFEARRAY *psaMethodArgs = NULL;
variant_t vtStringRet; //
// Load and start the .NET runtime.
// wprintf(L"Load and start the .NET runtime %s \n", pszVersion); hr = CLRCreateInstance(CLSID_CLRMetaHost, IID_PPV_ARGS(&pMetaHost));
if (FAILED(hr))
{
wprintf(L"CLRCreateInstance failed w/hr 0x%08lx\n", hr);
goto Cleanup;
} // Get the ICLRRuntimeInfo corresponding to a particular CLR version. It
// supersedes CorBindToRuntimeEx with STARTUP_LOADER_SAFEMODE.
hr = pMetaHost->GetRuntime(pszVersion, IID_PPV_ARGS(&pRuntimeInfo));
if (FAILED(hr))
{
wprintf(L"ICLRMetaHost::GetRuntime failed w/hr 0x%08lx\n", hr);
goto Cleanup;
} // Check if the specified runtime can be loaded into the process. This
// method will take into account other runtimes that may already be
// loaded into the process and set pbLoadable to TRUE if this runtime can
// be loaded in an in-process side-by-side fashion.
BOOL fLoadable;
hr = pRuntimeInfo->IsLoadable(&fLoadable);
if (FAILED(hr))
{
wprintf(L"ICLRRuntimeInfo::IsLoadable failed w/hr 0x%08lx\n", hr);
goto Cleanup;
} if (!fLoadable)
{
wprintf(L".NET runtime %s cannot be loaded\n", pszVersion);
goto Cleanup;
} // Load the CLR into the current process and return a runtime interface
// pointer. ICorRuntimeHost and ICLRRuntimeHost are the two CLR hosting
// interfaces supported by CLR 4.0. Here we demo the ICorRuntimeHost
// interface that was provided in .NET v1.x, and is compatible with all
// .NET Frameworks.
hr = pRuntimeInfo->GetInterface(CLSID_CorRuntimeHost,
IID_PPV_ARGS(&pCorRuntimeHost));
if (FAILED(hr))
{
wprintf(L"ICLRRuntimeInfo::GetInterface failed w/hr 0x%08lx\n", hr);
goto Cleanup;
} // Start the CLR.
hr = pCorRuntimeHost->Start();
if (FAILED(hr))
{
wprintf(L"CLR failed to start w/hr 0x%08lx\n", hr);
goto Cleanup;
} //
// Load the NET assembly. Call the static method GetStringLength of the
// class CSSimpleObject. Instantiate the class CSSimpleObject and call
// its instance method ToString.
// // The following C++ code does the same thing as this C# code:
//
// Assembly assembly = AppDomain.CurrentDomain.Load(pszAssemblyName);
// object length = type.InvokeMember("GetStringLength",
// BindingFlags.InvokeMethod | BindingFlags.Static |
// BindingFlags.Public, null, null, new object[] { "HelloWorld" });
// object obj = assembly.CreateInstance("CSClassLibrary.CSSimpleObject");
// object str = type.InvokeMember("ToString",
// BindingFlags.InvokeMethod | BindingFlags.Instance |
// BindingFlags.Public, null, obj, new object[] { }); // Get a pointer to the default AppDomain in the CLR.
hr = pCorRuntimeHost->GetDefaultDomain(&spAppDomainThunk);
if (FAILED(hr))
{
wprintf(L"ICorRuntimeHost::GetDefaultDomain failed w/hr 0x%08lx\n", hr);
goto Cleanup;
} hr = spAppDomainThunk->QueryInterface(IID_PPV_ARGS(&spDefaultAppDomain));
if (FAILED(hr))
{
wprintf(L"Failed to get default AppDomain w/hr 0x%08lx\n", hr);
goto Cleanup;
} // Load the .NET assembly.
wprintf(L"Load the assembly %s\n", pszAssemblyName);
hr = spDefaultAppDomain->Load_2(bstrAssemblyName, &spAssembly);
if (FAILED(hr))
{
wprintf(L"Failed to load the assembly w/hr 0x%08lx\n", hr);
goto Cleanup;
} // Get the Type of CSSimpleObject.
hr = spAssembly->GetType_2(bstrClassName, &spType);
if (FAILED(hr))
{
wprintf(L"Failed to get the Type interface w/hr 0x%08lx\n", hr);
goto Cleanup;
} // Call the static method of the class:
// public static int GetStringLength(string str); // Create a safe array to contain the arguments of the method. The safe
// array must be created with vt = VT_VARIANT because .NET reflection
// expects an array of Object - VT_VARIANT. There is only one argument,
// so cElements = 1.
psaStaticMethodArgs = SafeArrayCreateVector(VT_VARIANT, , );
LONG index = ;
hr = SafeArrayPutElement(psaStaticMethodArgs, &index, &vtStringArg);
if (FAILED(hr))
{
wprintf(L"SafeArrayPutElement failed w/hr 0x%08lx\n", hr);
goto Cleanup;
} // Invoke the "GetStringLength" method from the Type interface.
hr = spType->InvokeMember_3(bstrStaticMethodName, static_cast<BindingFlags>(
BindingFlags_InvokeMethod | BindingFlags_Static | BindingFlags_Public),
NULL, vtEmpty, psaStaticMethodArgs, &vtLengthRet);
if (FAILED(hr))
{
wprintf(L"Failed to invoke GetStringLength w/hr 0x%08lx\n", hr);
goto Cleanup;
} // Print the call result of the static method.
wprintf(L"Call %s.%s(\"%s\") => %s\n",
static_cast<PCWSTR>(bstrClassName),
static_cast<PCWSTR>(bstrStaticMethodName),
static_cast<PCWSTR>(vtStringArg.bstrVal),
vtLengthRet.lVal); // Instantiate the class.
hr = spAssembly->CreateInstance(bstrClassName, &vtObject);
if (FAILED(hr))
{
wprintf(L"Assembly::CreateInstance failed w/hr 0x%08lx\n", hr);
goto Cleanup;
} // Call the instance method of the class.
// public string ToString(); // Create a safe array to contain the arguments of the method.
psaMethodArgs = SafeArrayCreateVector(VT_VARIANT, , ); // Invoke the "ToString" method from the Type interface.
hr = spType->InvokeMember_3(bstrMethodName, static_cast<BindingFlags>(
BindingFlags_InvokeMethod | BindingFlags_Instance | BindingFlags_Public),
NULL, vtObject, psaMethodArgs, &vtStringRet);
if (FAILED(hr))
{
wprintf(L"Failed to invoke ToString w/hr 0x%08lx\n", hr);
goto Cleanup;
} // Print the call result of the method.
wprintf(L"Call %s.%s() => %s\n",
static_cast<PCWSTR>(bstrClassName),
static_cast<PCWSTR>(bstrMethodName),
static_cast<PCWSTR>(vtStringRet.bstrVal)); Cleanup: if (pMetaHost)
{
pMetaHost->Release();
pMetaHost = NULL;
}
if (pRuntimeInfo)
{
pRuntimeInfo->Release();
pRuntimeInfo = NULL;
}
if (pCorRuntimeHost)
{
// Please note that after a call to Stop, the CLR cannot be
// reinitialized into the same process. This step is usually not
// necessary. You can leave the .NET runtime loaded in your process.
//wprintf(L"Stop the .NET runtime\n");
//pCorRuntimeHost->Stop(); pCorRuntimeHost->Release();
pCorRuntimeHost = NULL;
} if (psaStaticMethodArgs)
{
SafeArrayDestroy(psaStaticMethodArgs);
psaStaticMethodArgs = NULL;
}
if (psaMethodArgs)
{
SafeArrayDestroy(psaMethodArgs);
psaMethodArgs = NULL;
} return hr;
}
第二种比较简单:
//
// FUNCTION: RuntimeHostV4Demo2(PCWSTR, PCWSTR)
//
// PURPOSE: The function demonstrates using .NET Framework 4.0 Hosting
// Interfaces to host a .NET runtime, and use the ICLRRuntimeHost interface
// that was provided in .NET v2.0 to load a .NET assembly and invoke its
// type. Because ICLRRuntimeHost is not compatible with .NET runtime v1.x,
// the requested runtime must not be v1.x.
//
// If the .NET runtime specified by the pszVersion parameter cannot be
// loaded into the current process, the function prints ".NET runtime <the
// runtime version> cannot be loaded", and return.
//
// If the .NET runtime is successfully loaded, the function loads the
// assembly identified by the pszAssemblyName parameter. Next, the function
// invokes the public static function 'int GetStringLength(string str)' of
// the class and print the result.
//
// PARAMETERS:
// * pszVersion - The desired DOTNETFX version, in the format “vX.X.XXXXX”.
// The parameter must not be NULL. It’s important to note that this
// parameter should match exactly the directory names for each version of
// the framework, under C:\Windows\Microsoft.NET\Framework[64]. Because
// the ICLRRuntimeHost interface does not support the .NET v1.x runtimes,
// the current possible values of the parameter are "v2.0.50727" and
// "v4.0.30319". Also, note that the “v” prefix is mandatory.
// * pszAssemblyPath - The path to the Assembly to be loaded.
// * pszClassName - The name of the Type that defines the method to invoke.
//
// RETURN VALUE: HRESULT of the demo.
//
HRESULT RuntimeHostV4Demo2(PCWSTR pszVersion, PCWSTR pszAssemblyPath,
PCWSTR pszClassName)
{
HRESULT hr; ICLRMetaHost *pMetaHost = NULL;
ICLRRuntimeInfo *pRuntimeInfo = NULL; // ICorRuntimeHost and ICLRRuntimeHost are the two CLR hosting interfaces
// supported by CLR 4.0. Here we demo the ICLRRuntimeHost interface that
// was provided in .NET v2.0 to support CLR 2.0 new features.
// ICLRRuntimeHost does not support loading the .NET v1.x runtimes.
ICLRRuntimeHost *pClrRuntimeHost = NULL; // The static method in the .NET class to invoke.
PCWSTR pszStaticMethodName = L"GetStringLength";
PCWSTR pszStringArg = L"HelloWorld";
DWORD dwLengthRet; //
// Load and start the .NET runtime.
// wprintf(L"Load and start the .NET runtime %s \n", pszVersion); hr = CLRCreateInstance(CLSID_CLRMetaHost, IID_PPV_ARGS(&pMetaHost));
if (FAILED(hr))
{
wprintf(L"CLRCreateInstance failed w/hr 0x%08lx\n", hr);
goto Cleanup;
} // Get the ICLRRuntimeInfo corresponding to a particular CLR version. It
// supersedes CorBindToRuntimeEx with STARTUP_LOADER_SAFEMODE.
hr = pMetaHost->GetRuntime(pszVersion, IID_PPV_ARGS(&pRuntimeInfo));
if (FAILED(hr))
{
wprintf(L"ICLRMetaHost::GetRuntime failed w/hr 0x%08lx\n", hr);
goto Cleanup;
} // Check if the specified runtime can be loaded into the process. This
// method will take into account other runtimes that may already be
// loaded into the process and set pbLoadable to TRUE if this runtime can
// be loaded in an in-process side-by-side fashion.
BOOL fLoadable;
hr = pRuntimeInfo->IsLoadable(&fLoadable);
if (FAILED(hr))
{
wprintf(L"ICLRRuntimeInfo::IsLoadable failed w/hr 0x%08lx\n", hr);
goto Cleanup;
} if (!fLoadable)
{
wprintf(L".NET runtime %s cannot be loaded\n", pszVersion);
goto Cleanup;
} // Load the CLR into the current process and return a runtime interface
// pointer. ICorRuntimeHost and ICLRRuntimeHost are the two CLR hosting
// interfaces supported by CLR 4.0. Here we demo the ICLRRuntimeHost
// interface that was provided in .NET v2.0 to support CLR 2.0 new
// features. ICLRRuntimeHost does not support loading the .NET v1.x
// runtimes.
hr = pRuntimeInfo->GetInterface(CLSID_CLRRuntimeHost,
IID_PPV_ARGS(&pClrRuntimeHost));
if (FAILED(hr))
{
wprintf(L"ICLRRuntimeInfo::GetInterface failed w/hr 0x%08lx\n", hr);
goto Cleanup;
} // Start the CLR.
hr = pClrRuntimeHost->Start();
if (FAILED(hr))
{
wprintf(L"CLR failed to start w/hr 0x%08lx\n", hr);
goto Cleanup;
} //
// Load the NET assembly and call the static method GetStringLength of
// the type CSSimpleObject in the assembly.
// wprintf(L"Load the assembly %s\n", pszAssemblyPath); // The invoked method of ExecuteInDefaultAppDomain must have the
// following signature: static int pwzMethodName (String pwzArgument)
// where pwzMethodName represents the name of the invoked method, and
// pwzArgument represents the string value passed as a parameter to that
// method. If the HRESULT return value of ExecuteInDefaultAppDomain is
// set to S_OK, pReturnValue is set to the integer value returned by the
// invoked method. Otherwise, pReturnValue is not set.
hr = pClrRuntimeHost->ExecuteInDefaultAppDomain(pszAssemblyPath,
pszClassName, pszStaticMethodName, pszStringArg, &dwLengthRet);
if (FAILED(hr))
{
wprintf(L"Failed to call GetStringLength w/hr 0x%08lx\n", hr);
goto Cleanup;
} // Print the call result of the static method.
wprintf(L"Call %s.%s(\"%s\") => %d\n", pszClassName, pszStaticMethodName,
pszStringArg, dwLengthRet); Cleanup: if (pMetaHost)
{
pMetaHost->Release();
pMetaHost = NULL;
}
if (pRuntimeInfo)
{
pRuntimeInfo->Release();
pRuntimeInfo = NULL;
}
if (pClrRuntimeHost)
{
// Please note that after a call to Stop, the CLR cannot be
// reinitialized into the same process. This step is usually not
// necessary. You can leave the .NET runtime loaded in your process.
//wprintf(L"Stop the .NET runtime\n");
//pClrRuntimeHost->Stop(); pClrRuntimeHost->Release();
pClrRuntimeHost = NULL;
} return hr;
}
native C++ 动态调用.NET DLL的更多相关文章
- C#实现动态调用Windows DLL
调用方法: object obj = WinDllInvoke("Kernel32.dll", "Beep", , }, typeof(void)); 函数代码 ...
- C# 中静态调用C++dll 和C# 中动态调用C++dll
在最近的项目中,牵涉到项目源代码保密问题,由于代码是C#写的,容易被反编译,因此决定抽取核心算法部分使用C++编写,C++到目前为止好像还不能被很好的反编译,当然如果你是反汇编高手的话,也许还是有可能 ...
- 关于C#动态调用VC Dll的方法(转)
http://blog.csdn.net/null1/article/details/3953155
- Delphi DLL的创建、静态及动态调用
转载:http://blog.csdn.net/welcome000yy/article/details/7905463 结合这篇博客:http://www.cnblogs.com/xumenger/ ...
- C#程序实现动态调用DLL的研究(转)
摘 要:在<csdn开发高手>2004年第03期中的<化功大法——将DLL嵌入EXE>一文,介绍了如何把一个动态链接库作为一个资源嵌入到可执行文件,在可执行文件运行时,自动从资 ...
- C#程序实现动态调用DLL的研究[转]
摘 要: 在< csdn 开发高手> 2004 年第 03 期中的<化功大法——将 DLL 嵌入 EXE >一文,介绍了如何把一个动态链接库作为一个资源嵌入到可执行文件,在 ...
- C#程序实现动态调用DLL的研究
摘 要:在<csdn开发高手>2004年第03期中的<化功大法——将DLL嵌入EXE>一文,介绍了如何把一个动态链接库作为一个资源嵌入到可执行文件,在可执行文件运行时,自动从资 ...
- [转]Delphi DLL的创建、静态 以及动态调用
第一章 DLL简单介绍 由于在目前的学习工作中,需要用到DLL文件,就学习了下,在这里作个总结. 首先装简单介绍下DLL: 1,减小可执行文件的大小 DLL技术的产生有很大一部分原因是为了减小可执行 ...
- C# 调用外部dll(转)
C# 调用外部dll 一. DLL与应用程序 动态链接库(也称为DLL,即为"Dynamic Link Library"的缩写)是Microsoft Windows最 ...
随机推荐
- websocket可以做什么
本篇介绍的是websocket,但是并不介绍它的协议格式,一般能看明白http头也能明白websocket在协议切换前的协商,能看明白IP报头也就对websocket在协议切换后通讯格式不陌生.web ...
- 微信小程序 子组件给父组件传参
子组件给父组件传参只需这4步: 子组件的两步: 1.子组件绑定函数 addInfo <button type="primary" bindtap="addInfo& ...
- vue动态样式设置
思路: 通过 v-bind:class="true ? style1 : style2 " 配合三元表达式完成样式的切换 具体实现 //return设置控制的参数 //有多个需要样 ...
- 详解 PHP 中的三大经典模式
单例模式 单例模式的含义: 作为对象的创建模式,单例模式确保某一个类只有一个实例,而且自行实例化并向整个系统全局地提供这个实例.它不会创建实例副本,而是会向单例类内部存储的实例返回一个引用. 单例模式 ...
- node后台初始配置(2)
一.node-app结构 创建成功node-app项目后,会自动生成一些文件一般初始的结构如下图 在bin文件夹里面只有一个文件www var port = normalizePort(pr ...
- python3 之 文件read方法(read、readline、readlines)
目录 一.read方法 二.readline方法 三.readlines方法 正文 python3中,读取文件有三种方法:read().readline().readlines(). 此三种方法,均支 ...
- linux history(命令历史)
1.bash中默认命令记忆可达1000个.这些命令保存在主文件夹内的.bash_history中. 2.~/.bash_history:记录的是前一次登录以前所执行过的命令.至于本次登录的命令暂时存储 ...
- linux 进程简介
进程相关知识简介 进程定义: 一个运行中的程序即一个process task struct: 内核存储进程信息的固定格式称为task struct,task struct记录了例如该进程内存下一跳位置 ...
- jquery浅复制和深复制区别
jquery浅复制和深复制区别
- DVWA学习之SQL注入
DVWA学习之SQL注入 环境工具 dvwa 1.9 phpstudy firefox burpsuite 实验步骤 一.设置安全级别为LOW 1. 登录DVWA,并将安全级别设置为LOW 2. 进入 ...