在C ++项目和C#项目之间传递指针而不在C#项目上使用不安全

时间:2016-04-03 09:06:03

标签: c# c++ interop

陷入非常天真的问题。我有两个项目,一个是C ++,另一个是C#。想法是使用C ++项目作为一些C库的包装。并在C#中执行实际逻辑。

传递Value类型非常方便。但是参考类型我很难 没有使用 不安全 DllImport 属性。

C ++

Cryptoki.Wrapper.h文件

using namespace System;
#pragma comment(lib, "legacy_stdio_definitions.lib")

namespace CryptokiWrapper {    
    public ref class CryptokiInit
    {
    public:
        char* TESTString(char* test);           
        double TESTDouble(double test);         
    };    
}

Cryptoki.Wrapper.cpp文件

#include "stdafx.h"
#include "Cryptoki.Wrapper.h"
using namespace std;
using namespace CryptokiWrapper;   

char* CryptokiInit::TESTString(char* test)
{
    char* r = test;     
    return r;
}

double CryptokiInit::TESTDouble(double test)
{
    unsigned long int r = test;     
    return r;
}

C#代码

using System;
using System.Runtime.InteropServices;

using CryptokiWrapper;

namespace CallCryptoki
{
    class Program
    {   
        //[MarshalAs(UnmanagedType.LPTStr)]
        //public String msg = "Hello World";   

        static void Main(string[] args)
        {
            CryptokiInit ob = new CryptokiInit();
            //This Works
            doubled d = ob.TESTDouble(99);

            //But having hard time accepting the char* reference 
            //or sending string as refrence without using unsafe
            // like
            string text = "Hello World!";
            string res = (*something*)ob.TESTString((*something*)text);
        }
    }
}

是否有任何类型的演员表(即 某事 )..... 无论如何,我能够轻松地执行此操作。 (只有参考传输就足够了,然后我可以构建字符串或对象)

就像另一个函数一样,使用double作为参数并返回类型。

虽然上面的例子只是说字符串,但是想要理解为概念,这样我就可以为两个项目之间的任何引用类型编写互操作(即C#和C ++)

提前感谢您的帮助!

1 个答案:

答案 0 :(得分:0)

首先,这不是简单的C ++,而是C ++ / CLI - 主要是为托管/非托管代码互操作性而设计的。

您的C ++ / CLI函数可以使用.NET的字符串类型,如下所示:

int digit = 0, letter = 0, punc = 0;
char c;
String sentence = "abc, (kl{}";

for (int a = 0; a<sentence.length(); a++){
    c=sentence.charAt(a);

    if(Character.isLetter(c))
        letter++;

    if(Character.isDigit(c))
        digit++;

    if(("" + c).matches("[\\p{Punct}]")){
        punc++;
    }    
 }
System.out.println(punc);
}

System::String^ TESTString(System::String^ test); 表示托管参考,将其视为^的托管等效文件。

现在,要在纯C ++中使用字符串数据,您有两种选择:

  • 编组 - 见Overview of Marshaling in C++

    例如,如果您需要将其转换为*,请执行以下操作:

    const char*
    #include <msclr/marshal.h>
    

    这将复制字符串数据,因为内存表示需要从2个字节的par字符更改为单个字符。

  • 直接以msclr::interop::marshal_context ctx; auto testCStr = ctx.marshal_as<const char*>(test); // testCStr is freed when ctx goes out of scope 访问内存。您需要事先固定字符串,以免GC移动它。

    const wchar_t*
    #include <vcclr.h>
    

    以这种方式修改字符串数据。

要将字符串发送回管理方,您可以使用pin_ptr<const wchar_t> testCStr = PtrToStringChars(test); // testCStr behaves just like a const wchar_t* ,也可以拨打marshal_as<System::String^>(yourCString);