从C#传递char**的引用到非托管C++

5

这是C#代码。

namespace CameraTest
{
    class Program
    {
        static void Main(string[] args)
        {
            string[] lst = new string[10];
            for (int i = 0; i < 10; i++)
            {
                lst[i] = new string(' ', 33);
            }
            bool sync = true;
            bool ret = CameraCalls.CAM_EnumCameraEx(sync, lst, 10, 33);

        }
    }

    public static class CameraCalls
    {
        [DllImport("CamDriver64.dll")]
        public static extern bool CAM_EnumCameraEx(bool sync,
                                                   [MarshalAs(UnmanagedType.LPArray)]
                                                   string[] lst, 
                                                   long maxCam, 
                                                   long maxChar);
    }
}

这就是未托管的方法。
BOOL WINAPI CAM_EnumCameraEx(BOOL bSynchronized, char **ppCameraList, long lMaxCamera, long lMaxCharacter);

这个方法是往一个字符串数组中写入内容的。那么有没有办法从C#调用这个方法,让非托管代码能够往这个字符串数组中写入内容呢?


3
合适的翻译如下:序:本文主要介绍如何在.NET Framework中序列化和反序列化不同类型的数组。Marshaling Different Types of Arrays本文主要介绍如何在.NET Framework中序列化和反序列化不同类型的数组。在使用平台调用来与非托管代码进行交互时,可以使用 Marshal 类提供的各种方法从托管代码传输数组数据到非托管代码,以及从非托管代码接收数组数据并传输到托管代码。常见的数组类型包括单维、多维、字符串和结构体等。Marshal 类中的各种方法可以根据数组类型执行以下操作:
  1. 对于单维数组,可以使用 Marshal.Copy 方法将数组复制到非托管内存或从非托管内存中复制数组。
  2. 对于多维数组,可以使用 Marshal.UnsafeAddrOfPinnedArrayElement 方法获取数组元素地址,并在非托管代码中使用该地址。
  3. 对于字符串数组,可以使用 Marshal.StringToHGlobalAnsi 或 Marshal.StringToHGlobalUni 方法将字符串复制到非托管内存中。
  4. 对于结构体数组,可以使用 GCHandle.Alloc 方法固定数组并获取其地址,然后使用 Marshal.PtrToStructure 方法将其转换为对应类型的非托管结构体指针。
以上这些方法都需要谨慎使用,确保在处理非托管内存时遵循正确的规则和最佳实践。希望这篇文章能够帮助您了解如何序列化和反序列化不同类型的数组。
- Remus Rusanu
那份文档中已经有了答案,我所要做的只是使用输入输出。 - Adam Nester
1个回答

1

谢谢Remus Rusanu!他提供的链接给出了答案。我所需要做的就是在lst参数上添加[In, Out]修饰符。

namespace CameraTest
{
    class Program
    {
        static void Main(string[] args)
        {
            int maxCam = 10,
                 maxChar = 33;

            var lst = (new object[maxCam]).Select(o => new string(' ', maxChar)).ToArray();
            bool sync = true;
            bool ret = CameraCalls.CAM_EnumCameraEx(sync, lst, maxCam, maxChar);

        }
    }

    public static class CameraCalls
    {
        [DllImport("CamDriver64.dll")]
        public static extern bool CAM_EnumCameraEx(bool sync,
                                                   [In, Out]
                                                   string[] lst, 
                                                   long maxCam, 
                                                   long maxChar);
    }
}

刚用 StringBuilder[] 测试了一下我的答案,结果出现了堆栈不平衡的错误,所以我认为 @HansPassant 是正确的。但我还是很高兴我的创建任何对象新数组的方法已经开始流行 :) - huysentruitw
直到我添加了 [In, Out] 才起作用,否则它会要么不设置字符串,要么抛出内存异常。所以,如果 [In,Out] 是错误的,那么从外部方法获取数据的正确方法是什么?我应该使用什么代替 long? - Adam Nester
我不太愿意花时间帮忙。你已经回答了自己的问题,这表明你已经下定决心了。 - David Heffernan

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接