如何将C#字符串[]转换为System.IntPtr
本文关键字:转换 System IntPtr 字符串 | 更新日期: 2023-09-27 18:20:04
我需要在应用程序中使用本机dll结构。dll.h文件中的结构体da_i2k_input_file_info为
struct DA_I2K_EXPORT_API da_i2k_input_file_info {
const WDCHAR * image_path;
const WDCHAR ** image_files;
int num_images;
};
这就是如果用C++编写的用户代码的样子
in_file_info.num_images = 3;
in_file_info.image_files = new const WDCHAR*[in_file_info.num_images];
in_file_info.image_files[0] = WSTR("IMG_8670.JPG");
in_file_info.image_files[1] = WSTR("IMG_8671.JPG");
in_file_info.image_files[2] = WSTR("IMG_8672.JPG");
但是这个C#代码
[StructLayout(LayoutKind.Sequential)]
public struct da_i2k_input_file_info
{
[MarshalAs(UnmanagedType.LPTStr)]
public string image_path;
public IntPtr image_files;
public int num_images;
}
var openFileDialog = new OpenFileDialog{Multiselect = true};
da_i2k_input_file_info in_file_info;
in_file_info.image_path = null; // use full path in .image_files
in_file_info.num_images = openFileDialog.FileNames.Length;
in_file_info.image_files = openFileDialog.FileNames;
导致此错误
无法将类型"string[]"隐式转换为"System.IntPtr"
将openFileDialog.FileNames强制转换为IntPtr没有帮助。如何从openFileDialog.FileNames加载in_file_info.image_files?
编辑:OP在此交叉发布
我认为您需要将结构更改为如下所示:
[StructLayout(LayoutKind.Sequential)]
public struct da_i2k_input_file_info
{
[MarshalAs(UnmanagedType.LPTStr)]
public string image_path;
[MarshalAs(UnmanagedType.LPArray)]
public string[] image_files;
public int num_images;
}
这里发布了一个有效的答案。
代码如下
(包括tomfanning)
private static void DoTest()
{
var openFileDialog = new OpenFileDialog { Multiselect = true };
da_i2k_input_file_info in_file_info;
openFileDialog.ShowDialog();
in_file_info.image_path = null; // use full path in .image_files
in_file_info.num_images = openFileDialog.FileNames.Length;
// Create an array of IntPtrs.
IntPtr[] image_files_array = new IntPtr[in_file_info.num_images];
// Each IntPtr array element will point to a copy of a
// string element in the openFileDialog.FileNames array.
for (int i = 0; i < openFileDialog.FileNames.Length; i++)
{
image_files_array[i] = Marshal.StringToCoTaskMemUni(openFileDialog.FileNames[i]);
}
// In order to obtain the address of the IntPtr array,
// we must fix it in memory. We do this using GCHandle.
GCHandle gch = GCHandle.Alloc(image_files_array, GCHandleType.Pinned);
// pimage_files will point to the head of the IntPtr array.
IntPtr pimage_files = gch.AddrOfPinnedObject();
// Set pimage_files as the value of the "image_files" field/
in_file_info.image_files = pimage_files;
// Call a Test API.
TestStructure(in_file_info);
// After the API is called, free the GCHandle.
gch.Free();
// Free each string contained in the IntPtr array.
for (int i = 0; i < openFileDialog.FileNames.Length; i++)
{
Marshal.FreeCoTaskMem(image_files_array[i]);
}
}