如何使用 DLLImport 将字符串从 C# 传递到 C++(以及从 C++ 到 C#)?

Posted

技术标签:

【中文标题】如何使用 DLLImport 将字符串从 C# 传递到 C++(以及从 C++ 到 C#)?【英文标题】:How to pass strings from C# to C++ (and from C++ to C#) using DLLImport? 【发布时间】:2012-06-03 17:00:01 【问题描述】:

很长一段时间以来,我一直在尝试向/从 C# 向/从 C++ 发送一个字符串,但还没有设法让它工作......

所以我的问题很简单: 有谁知道将字符串从 C# 发送到 C++ 以及从 C++ 发送到 C# 的某种方法? (一些示例代码会有所帮助)

【问题讨论】:

【参考方案1】:

Windows API 中遇到的许多函数都采用字符串或字符串类型的参数。对这些参数使用字符串数据类型的问题在于,.NET 中的字符串数据类型一旦创建就不可更改,因此 StringBuilder 数据类型是这里的正确选择。例如,检查 API 函数 GetTempPath()

Windows API 定义

DWORD WINAPI GetTempPath(
  __in   DWORD nBufferLength,
  __out  LPTSTR lpBuffer
);

.NET 原型

[DllImport("kernel32.dll")]
public static extern uint GetTempPath
(
uint nBufferLength, 
StringBuilder lpBuffer
);

用法

const int maxPathLength = 255;
StringBuilder tempPath = new StringBuilder(maxPathLength);
GetTempPath(maxPathLength, tempPath);

【讨论】:

【参考方案2】:

在你的 c 代码中:

extern "C" __declspec(dllexport)
int GetString(char* str)



extern "C" __declspec(dllexport)
int SetString(const char* str)


在.net端:

using System.Runtime.InteropServices;


[DllImport("YourLib.dll")]
static extern int SetString(string someStr);

[DllImport("YourLib.dll")]
static extern int GetString(StringBuilder rntStr);

用法:

SetString("hello");
StringBuilder rntStr = new StringBuilder();
GetString(rntStr);

【讨论】:

您的const 使用倒退了。 这些示例在 VisStudio 2012 中因堆栈异常而爆炸,直到我将 cdecl 添加到 C# 和 C.... extern "C" __declspec(dllexport) int __cdecl SetString(... 然后 . .. [DllImport("YourLib.dlll", CallingConvention = CallingConvention.Cdecl)]...【参考方案3】:

将字符串从 C# 传递到 C++ 应该是直截了当的。 PInvoke 将为您管理转换。

可以使用 StringBuilder 将字符串从 C++ 获取到 C#。您需要获取字符串的长度才能创建正确大小的缓冲区。

以下是众所周知的 Win32 API 的两个示例:

[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
 static extern int GetWindowText(IntPtr hWnd, StringBuilder lpString, int nMaxCount);
public static string GetText(IntPtr hWnd)
 
     // Allocate correct string length first
     int length       = GetWindowTextLength(hWnd);
     StringBuilder sb = new StringBuilder(length + 1);
     GetWindowText(hWnd, sb, sb.Capacity);
     return sb.ToString();
 


[DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)]
 public static extern bool SetWindowText(IntPtr hwnd, String lpString);
SetWindowText(Process.GetCurrentProcess().MainWindowHandle, "Amazing!");

【讨论】:

以上是关于如何使用 DLLImport 将字符串从 C# 传递到 C++(以及从 C++ 到 C#)?的主要内容,如果未能解决你的问题,请参考以下文章

使用 Dllimport 将一个非常大的字符串作为字节数组从 C++ 传递到 C#

如何在 C# 中将 DLLImport 与结构一起用作参数?

C#DllImport传参

调用从 c# 返回 char* 的 c++ dll 函数。无法使用 DllImport()

如何将字符串从 C++ 原生传递到 C# Unity?

有啥方法可以调试从 C# DllImport 调用的 c++ dll?