【问题标题】:How to call managed C++ methods from Un-managed C++如何从非托管 C++ 调用托管 C++ 方法
【发布时间】:2013-03-24 06:11:49
【问题描述】:

请看下面的更新

(已解决)此外,我已将其扩展到第二个问题 Implement a C# DLL COM File In Unmanaged C++ Program

我已经研究到了互联网的尽头,但没有找到一个真实的、可理解的、人性化的例子来说明如何做到这一点。

我有一个加密和解密文本的 C# DLL。

我不想/不具备用 C++ 非托管代码重写它的智力能力。因此,我创建了一个与 C# dll 接口的 C++/CLR 类。

现在我需要知道如何从我的非托管代码中调用托管 C++。

这是我的托管代码,并且已验证它可以工作

// clrTest.cpp : main project file.

#include "cSharpRiJHarn"
#include "stdafx.h"
#include <string>
#include <stdio.h>

using namespace cSharpRiJHarn;
using namespace System;


String^ Encrypt(String ^s)
{
    return  RijndaelLink::encrypt(s);   
}


String^ Decrypt(String ^s)
{
    return  RijndaelLink::decrpyt(s);   
}

int main()
{   
     //Console::WriteLine(Encrypt("It Works"));

     //Console::WriteLine(Decrypt(Encrypt("It Works")));

     //Console::ReadLine();
     return 0;
}

现在我再次对此进行了研究。

我已经看到了所有糟糕/过于复杂的解释

我知道我需要使用一种叫做 COM 或 Interop 的东西

我不知道这是如何工作的,我只是在寻找一个非常简单的解释。

感谢您的帮助。

更新

我已将 C# DLL 转换为 COM 文件

using System;
using System.Runtime.InteropServices;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace cSharpRiJHarn
{
    [Guid("GuiD CODE REMOVED")]
    public interface DBCOM_Interface
    {
        [DispId(1)]
        String encrypt(string s);
        [DispId(2)]
        String decrpyt(string s);
    }

    [Guid("GuiD CODE REMOVED"),
    InterfaceType(ComInterfaceType.InterfaceIsIDispatch)]
    public interface DBCOM_Events
    {
    }

    [Guid("GuiD CODE REMOVED"),
    ClassInterface(ClassInterfaceType.None),
    ComSourceInterfaces(typeof(DBCOM_Events))]
    public class RijndaelLink : DBCOM_Interface
    {
        public String encrypt(String s)
        {
            return Rijndael.EncryptString(s); 
        }
        public String decrpyt(String s)
        {
            return Rijndael.DecryptString(s);
        }
    }
}

现在我只需要知道如何在非托管 C++ 中实现它... 我已尝试将文件仅添加到 C++ 项目中,并将整个 cSharpRiJHarn 项目添加到此解决方案中。都不行。

#import "cSharpRiJHarn" 
#include "stdafx.h"
#include <string>
#include <stdio.h>
#include <iostream>
//using namespace cSharpRiJHarn;


int main(){

    cSharpRiJHarn::RijndaelLink::encrypt("It works");
    char ch;
    std::cin>>ch;
    return 0;
}

这是我遇到的错误之一。

错误 6 错误 C2653: 'cSharpRiJHarn' : 不是类或命名空间 名字

错误 8 IntelliSense:无法打开源文件 "C:/.../.../Documents/Visual Studio 2010/项目/unmannagedCPPExample/unmannagedCPPExample/Debug/cSharpRiJHarn.tlh" c:......\documents\visual 工作室 2010\projects\unmannagedcppexample\unmannagedcppexample\unmannagedcppexample.cpp

【问题讨论】:

  • 最好找到 AES/Rijndael 的非托管实现。 Microsoft CryptoAPI 中有一个。它会更干净。
  • Robert Giesecke 的 UnmanagedExports 满足您的要求。
  • 这很容易理解和实现:blogs.microsoft.co.il/blogs/sasha/archive/2008/02/16/… 你可能甚至不需要 dllexport 部分。

标签: c++ com interop unmanaged managed-c++


【解决方案1】:

你可以使用微软提供的很酷的C++ Marshaling library,像这样:

#include "cSharpRiJHarn"
#include "stdafx.h"
#include <string>
#include <stdio.h>
#include "msclr\marshal_cppstd.h" // marshaling library

using namespace cSharpRiJHarn;
using namespace System;
using namespace msclr::interop; // marshaling library

std::wstring Encrypt(std::wstring s)
{
    return marshal_as<std::wstring>(RijndaelLink::encrypt(marshal_as<String^>(s)));
}

std::wstring Decrypt(std::wstring s)
{
    return marshal_as<std::wstring>(RijndaelLink::decrypt(marshal_as<String^>(s)));
}

【讨论】:

  • 我把它放在我的无人管理的代码文件中,大约有 60 个错误。我认为这与参考有关。我需要将我的托管代码添加到此解决方案吗?我还需要做些什么来参考这个吗?当我右键单击我的项目并尝试添加引用时,它说我不能。
  • 如果您的初始代码也可以正常编译,这应该可以正常编译。是这样吗?
  • 我的 C# DLL 编译良好。托管 C++ 项目编译良好且运行良好。当我创建一个非托管 C++ 项目时,放入您的代码,添加其他项目并尝试编译它不会运行。它一直说 marshal.h 文件中有错误,所以我认为某处存在参考错误。或者我将所有这些都错误地实施了。
  • 这是其中之一 14 IntelliSense:此声明没有存储类或类型说明符 c:\program files (x86)\microsoft visual studio 10.0\vc\include\msclr\marshal.h 185 1
  • 哦,当您说“如何从我的非托管代码中调用托管 C++”时,我以为您会将非托管 C++ 代码与托管 C++ 代码放在同一个项目中(我的代码就是这样做的) )。如果它是一个外部非托管 DLL,那么您需要 COM 或 P/Invoke(DLL 导出 DLL 导入,如 David Heffernan 所指出的,带有 UnmanagedExports 之类的东西)。在这种情况下,您实际上并不需要中间托管的 C++ 项目。
【解决方案2】:

首先,您的方法接收并返回一个String^,它是一个托管对象。非托管代码不知道这种类型,也不能创建这样的对象。因此,您需要包装函数调用,以便函数将托管类型编组为非托管代码可以理解的内容。

之后,您可以将 DllExport 属性添加到托管方法中,如 here 所述。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2010-12-25
    • 1970-01-01
    • 2013-09-30
    • 2013-01-07
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多