Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/156.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 在本机C++;_C#_C++_.net - Fatal编程技术网

C# 在本机C++;

C# 在本机C++;,c#,c++,.net,C#,C++,.net,我想将.net类传递给本机函数并使用该类(即获取属性值)。请注意,我不想使用C++/CLI 例如,我的Web应用程序中有一个标签,我想在我的C++代码中获得文本属性。 我的尝试 我尝试在C++中加载CLR,读取在C语言中实例化的标签的文本属性,但是遇到Syt.Access违规例外。< /P> 这是我的密码: C# C++ extern“C”\u declspec(dllexport)void ReadDotNetClass(\u TypePtr labelTypePtr) { PCWSTR

我想将.net类传递给本机函数并使用该类(即获取属性值)。请注意,我不想使用C++/CLI

例如,我的Web应用程序中有一个标签,我想在我的C++代码中获得文本属性。 我的尝试 我尝试在C++中加载CLR,读取在C语言中实例化的标签的文本属性,但是遇到Syt.Access违规例外。< /P> 这是我的密码:

C#

C++

extern“C”\u declspec(dllexport)void ReadDotNetClass(\u TypePtr labelTypePtr)
{
PCWSTR pszVersion=L“v4.0.30319”;
PCWSTR pszAssemblyName=L“System.Web,Version=4.0.0.0,Culture=neutral,PublicKeyToken=b03f5f7f11d50a3a”;
PCWSTR pszClassName=L“System.Web.UI.WebControls.Label”;
ICLRMetaHost*pMetaHost=NULL;
ICLRRuntimeInfo*pRuntimeInfo=NULL;
ICorRuntimeHost*pCorRuntimeHost=NULL;
IUnknownPtr spAppDomainThunk=NULL;
_AppDomainPtr spDefaultAppDomain=NULL;
//要加载的.NET程序集。
bstr_t bstrAssemblyName(pszAssemblyName);
_AssemblyPtr SPAAssembly=NULL;
//要实例化的.NET类。
bstr_t bstrClassName(pszClassName);
变量对象;
//要调用的.NET类中的实例方法。
bstr_t bstrMethodName(L“文本”);
SAFEARRAY*psaMethodArgs=NULL;
变体vtStringRet;
CLRCreateInstance(CLSID_CLRMetHost、IID_PPV_参数(&pMetaHost));
pMetaHost->GetRuntime(pszVersion,IID_PPV_ARGS(&pRuntimeInfo));
布尔可浮;
pRuntimeInfo->IsLoadable(&fLoadable);
pRuntimeInfo->GetInterface(CLSID_CorRuntimeHost、IID_PPV_ARGS(&pCorRuntimeHost));
pCorRuntimeHost->Start();
pCorRuntimeHost->GetDefaultDomain(&SPAppDomainInthunk);
spAppDomainThunk->查询接口(IID_PPV_ARGS(&spDefaultAppDomain));
spDefaultAppDomain->Load_2(bstrAssemblyName和spAssembly);
psaMethodArgs=SafeArrayCreateVector(VT_变量,0,0);
//从类型接口调用方法。
//此处发生System.AccessViolationException异常
HRESULT hr=labelTypePtr->InvokeMember\u 3(bstrMethodName,静态类型转换(
BindingFlags_实例| BindingFlags_公共| BindingFlags_GetProperty),
NULL、vtObject、psaMethodArgs和vtStringRet);
如果(失败(小时))
wprintf(L“调用方法w/hr 0x%08lx\n失败”,hr);
}
< C++代码是简化版的。


请注意,我只需要在本地C++中处理.NET类(不是我自己的类),我不想使用COM或其他方法出现在本地世界的边上。

< P> <代码>。但是,您并没有将创建的实例传递给ReadDotNetClass函数,只是传递标签的
类型的句柄。请注意,如果从托管代码调用本机函数,则不需要初始化CLR—它已经初始化,正在运行托管代码。因此,在本机函数签名中包含一个指向托管对象的指针,在调用本机函数时将其与指向托管对象的
Type
指针一起传递,在本机函数内部只需调用
Type
实例上的
InvokeMember
,传递托管对象作为<代码>目标< /代码>参数-删除所有CLR初始化的东西。

我对此一无所知,但作为定位问题的起点,C++程序中的哪一个语句究竟是获得Stase.Access违规异常?那是.NET异常还是C++运行时异常?我真的不明白你想做什么。在C#程序中,Label对象是WinForms标签吗?如果是这样的话,看起来您正在尝试使用WinForms数据,而无需通过Application.Run启动Windows消息泵来设置整个WinForms环境。而且我真的无法想象将.Net WiFrices程序集加载到本地C++程序中是可能的。这毫无意义。我所说的和我的代码只是一个例子。对我来说,把几行代码放入C++中,以防止我的C语言应用程序容易地被分解,改变我的代码的重要部分是很重要的。我评论了我从哪里得到的异常,但我不知道那是什么样的异常。我还注意到我的示例是关于Web应用程序中的标签的。(比我通常更喜欢:-)如果您的目标是防止.Net代码被反汇编,那么这不是实现的方法。您需要的是一个模糊处理实用程序。有很多,有些是免费的,有些是非常昂贵的。我花了几个月的时间进行模糊处理。但这无论如何都没有帮助。我看到许多.net程序集被破解,甚至是新手用户。所以,请相信我,关注问题本身。:-)我删除了整个CLR初始化代码,我只是传递对象实例,它的类型为C++中的变量参数类型,而且工作正常。谢谢但正如您所说,我应该而且我想传递实例,它是按指针类型传递的。但是我不知道如何在InvokeMember中使用指针作为目标。运行您链接的代码示例,我可以看到变量类型需要是
VT\u UNKNOWN
。要从托管对象实例获取
IUnknown
指针,请使用-不使用
GCHandle
。我将通过
marshall.getiunknownfobject
获取的指针传递到
IUnknown*
参数,但是我仍然不知道如何将
IUnknown*
转换为
VARIANT
。helper类有两个和一个接受
IUnknown*
。您应该能够编写
vtObject=pUnknown
static void Main(string[] args)
{
    var label = new Label { Text = "Some Text" };

    //Send Type because CLR Invocation is defined on object's Type
    var labelType = label.GetType();

    GCHandle gch = GCHandle.Alloc(labelType);

    IntPtr labelTypeIntPtr = GCHandle.ToIntPtr(gch);

    ReadDotNetClass(labelTypeIntPtr);
}

//native function definition
[DllImport("Unmanaged.dll")]
private static extern void ReadDotNetClass(IntPtr labelTypeIntPtr);
extern "C" __declspec(dllexport) void ReadDotNetClass(_TypePtr labelTypePtr)
{
    PCWSTR pszVersion = L"v4.0.30319";
    PCWSTR pszAssemblyName= L"System.Web, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a";
    PCWSTR pszClassName=L"System.Web.UI.WebControls.Label";

    ICLRMetaHost *pMetaHost = NULL;
    ICLRRuntimeInfo *pRuntimeInfo = NULL;
    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);
    variant_t vtObject;

    // The instance method in the .NET class to invoke.
    bstr_t bstrMethodName(L"Text");
    SAFEARRAY *psaMethodArgs = NULL;
    variant_t vtStringRet;

    CLRCreateInstance(CLSID_CLRMetaHost, IID_PPV_ARGS(&pMetaHost));
    pMetaHost->GetRuntime(pszVersion, IID_PPV_ARGS(&pRuntimeInfo));

    BOOL fLoadable;
    pRuntimeInfo->IsLoadable(&fLoadable);
    pRuntimeInfo->GetInterface(CLSID_CorRuntimeHost, IID_PPV_ARGS(&pCorRuntimeHost));
    pCorRuntimeHost->Start();
    pCorRuntimeHost->GetDefaultDomain(&spAppDomainThunk);
    spAppDomainThunk->QueryInterface(IID_PPV_ARGS(&spDefaultAppDomain));
    spDefaultAppDomain->Load_2(bstrAssemblyName, &spAssembly);
    psaMethodArgs = SafeArrayCreateVector(VT_VARIANT, 0, 0);

    //Invoke method from the Type interface.
    //System.AccessViolationException occurred here
    HRESULT hr = labelTypePtr->InvokeMember_3(bstrMethodName, static_cast<BindingFlags>(
        BindingFlags_Instance | BindingFlags_Public | BindingFlags_GetProperty),
        NULL, vtObject, psaMethodArgs, &vtStringRet);
    if (FAILED(hr))
        wprintf(L"Failed to invoke Method w/hr 0x%08lx\n", hr);
}