2012-01-12 38 views
1

我需要在我的应用程序中使用本机dll结构。在DLL .h文件中 结构da_i2k_input_file_info是如何将C#string []转换为System.IntPtr?

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; 

导致此错误

C注释隐式地将类型'string []'转换为'System.IntPtr'

作为IntPtr铸造openFileDialog.FileNames没有帮助。 如何从openFileDialog.FileNames加载in_file_info.image_files?

编辑:OP cross posted this here

回答

0

一个工作的答案被张贴here

代码如下。
(由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]); 
     } 
    } 
1

我相信你需要改变你的结构来如下:

[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; 
} 
+1

它不会建立与运行过程中的变化,但休息。改变'公共的IntPtr image_files'到'[的MarshalAs(UnmanagedType.LPArray)]公共串[] image_files'导致'System.TypeLoadException:不可以键入 'da_i2k_input_file_info' 的编组场 'image_files':无效的托管/非托管类型组合(数组字段必须与ByValArray或成对的SafeArray)'。我也试图改变LPArray到ByValArray和安全数组但也不能工作。我相信image_files需要有一个IntPtr。 – jacknad 2012-01-12 20:48:56

相关问题