在 C++ 项目和 C# 项目之间传递指针而不在 C# 项目上使用不安全
Passing Pointer between C++ Project and C# Project without using unsafe on C# project
陷入非常幼稚的问题。我有两个项目,一个在 C++ 中,另一个在 C# 中。想法是使用 C++ 项目作为一些 C 库的包装器。并在 C# 中执行实际逻辑。
传递Value类型很方便。但是对于参考类型,我很难 WITHOUT USING unsafe or 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);
}
}
}
是否有任何类型的演员表(即某物)......
无论如何我可以轻松地执行此操作。 (只有引用传输就足够了,然后我可以构建字符串或对象)
就像另一个函数一样,使用双精度作为参数和 return 类型。
虽然上面的例子只谈到了字符串,但我想理解为概念,这样我就可以为两个项目(即 C# 和 C++)之间的任何引用类型编写互操作
在此先感谢您的帮助!
首先,这不是普通的 C++,而是 C++/CLI - 主要为 managed/unmanaged 代码互操作性而设计。
您的 C++/CLI 函数可以像这样使用 .NET 的字符串类型:
System::String^ TESTString(System::String^ test);
^
表示 托管引用 ,将其视为 *
.
的托管等效项
现在,要在纯 C++ 中使用字符串数据,您有两个选择:
编组它 - 参见 Overview of Marshaling in C++
例如,如果您需要将其转换为 const char*
,请执行以下操作:
#include <msclr/marshal.h>
msclr::interop::marshal_context ctx;
auto testCStr = ctx.marshal_as<const char*>(test);
// testCStr is freed when ctx goes out of scope
这将复制字符串数据,因为内存表示需要从 2 字节 par 字符更改为单个字符。
直接访问内存为const wchar_t*
。您需要事先 pin 字符串,这样它就不会被 GC 移动。
#include <vcclr.h>
pin_ptr<const wchar_t> testCStr = PtrToStringChars(test);
// testCStr behaves just like a const wchar_t*
不要以这种方式修改字符串数据。
要将字符串发送回托管端,您可以使用 marshal_as<System::String^>(yourCString)
,或调用 gcnew System::String(yourCString)
;
陷入非常幼稚的问题。我有两个项目,一个在 C++ 中,另一个在 C# 中。想法是使用 C++ 项目作为一些 C 库的包装器。并在 C# 中执行实际逻辑。
传递Value类型很方便。但是对于参考类型,我很难 WITHOUT USING unsafe or 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);
}
}
}
是否有任何类型的演员表(即某物)...... 无论如何我可以轻松地执行此操作。 (只有引用传输就足够了,然后我可以构建字符串或对象)
就像另一个函数一样,使用双精度作为参数和 return 类型。
虽然上面的例子只谈到了字符串,但我想理解为概念,这样我就可以为两个项目(即 C# 和 C++)之间的任何引用类型编写互操作
在此先感谢您的帮助!
首先,这不是普通的 C++,而是 C++/CLI - 主要为 managed/unmanaged 代码互操作性而设计。
您的 C++/CLI 函数可以像这样使用 .NET 的字符串类型:
System::String^ TESTString(System::String^ test);
^
表示 托管引用 ,将其视为 *
.
现在,要在纯 C++ 中使用字符串数据,您有两个选择:
编组它 - 参见 Overview of Marshaling in C++
例如,如果您需要将其转换为
const char*
,请执行以下操作:#include <msclr/marshal.h>
msclr::interop::marshal_context ctx; auto testCStr = ctx.marshal_as<const char*>(test); // testCStr is freed when ctx goes out of scope
这将复制字符串数据,因为内存表示需要从 2 字节 par 字符更改为单个字符。
直接访问内存为
const wchar_t*
。您需要事先 pin 字符串,这样它就不会被 GC 移动。#include <vcclr.h>
pin_ptr<const wchar_t> testCStr = PtrToStringChars(test); // testCStr behaves just like a const wchar_t*
不要以这种方式修改字符串数据。
要将字符串发送回托管端,您可以使用 marshal_as<System::String^>(yourCString)
,或调用 gcnew System::String(yourCString)
;