如何使用C#获取字符**?

如何使用C#获取字符**?,c#,char,marshalling,dllimport,unsafe,C#,Char,Marshalling,Dllimport,Unsafe,我需要以以下形式将参数传递给不安全的DllImported函数: [DllImport("third_party.dll")] private static extern unsafe int start(int argc, char** argv); 我假设它是一个字符串数组。但是,当我尝试执行以下操作时,会出现“无法从字符串[]转换为字符**”错误。我怎样才能让它工作呢?谢谢 string[] argv = new string[] { }; start(0, argv); 编辑1: 这

我需要以以下形式将参数传递给不安全的DllImported函数:

[DllImport("third_party.dll")]
private static extern unsafe int start(int argc, char** argv);
我假设它是一个字符串数组。但是,当我尝试执行以下操作时,会出现“无法从字符串[]转换为字符**”错误。我怎样才能让它工作呢?谢谢

string[] argv = new string[] { };
start(0, argv);
编辑1: 这个问题被标记为重复的,但是看看可能重复的问题,我仍然不知道如何让它工作

编辑2:进一步分类问题和所需参数。它看起来像您的标准argc/argv参数(参数计数,然后是参数值)。与启动c程序的方法相同:
intmain(intargc,char**argv)
编辑3:
我从第三方图书馆供应商那里得到了更多信息。这是:

  • 第一个参数是参数的计数
  • 第二个参数是以null结尾的字符串数组
  • 字符串是ANSI编码的
编辑4:使用有效解决方案进行最终编辑(至少在我的情况下)。我想把这个作为答案,但不能,因为这个问题被标记为重复。这是一个对我帮助最大的问题。最后,dll函数需要一个指向带有ANSI字符串的缓冲区的指针数组。因此,我的最终方法(基于链接问题)如下所示。在内存中创建一个数组来保存指针,然后将每个字符串分配到内存中的其他位置,并将指针写入第一个指针数组中的那些字符串。此代码在生产中起作用:

[DllImport("third_party.dll", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
private static extern int start(Int32 args, IntPtr argv);

public bool start(params string[] arguments)
{
    int result;

    if (arguments == null || arguments.Length == 0)
    {
        result = dll_system_startup(0, IntPtr.Zero);
    }
    else
    {
        List<IntPtr> allocatedMemory = new List<IntPtr>();

        int sizeOfIntPtr = Marshal.SizeOf(typeof(IntPtr));
        IntPtr pointersToArguments = Marshal.AllocHGlobal(sizeOfIntPtr * arguments.Length);

        for (int i = 0; i < arguments.Length; ++i)
        {
            IntPtr pointerToArgument = Marshal.StringToHGlobalAnsi(arguments[i]);
            allocatedMemory.Add(pointerToArgument);
            Marshal.WriteIntPtr(pointersToArguments, i * sizeOfIntPtr, pointerToArgument);
        }

        result = start(arguments.Length, pointersToArguments);

        Marshal.FreeHGlobal(pointersToArguments);

        foreach (IntPtr pointer in allocatedMemory)
        {
            Marshal.FreeHGlobal(pointer);
        }
    }

    return result == 0;
}
[DllImport(“第三方.dll”,CallingConvention=CallingConvention.Cdecl,CharSet=CharSet.Ansi)]
私有静态外部intstart(Int32 args、IntPtr argv);
public bool start(参数字符串[]参数)
{
int结果;
if(arguments==null | | arguments.Length==0)
{
结果=dll\u系统\u启动(0,IntPtr.Zero);
}
其他的
{
List allocatedMemory=新列表();
int-sizeofintpttr=Marshal.SizeOf(typeof(IntPtr));
IntPtr pointersToArguments=Marshal.AllocHGlobal(sizeofintpttr*arguments.Length);
for(int i=0;i
能否将DllImport声明参数类型更改为
StringBuilder[]
?然后您可以调用如下函数:

StringBuilder[] args = new StringBuilder[] { };
start(args);

我想你可能需要用马歇尔

var a = (char*)Marshal.StringToCoTaskMemAuto("myString");
char** = &a;

这只是一个猜测,因为我没有一个接受字符**的库,所以我无法尝试它。

相当于C的
char**
是C中完全固定的
byte[][]
(完全固定是指外部数组和所有内部数组)。如果您想传递C#字符串,您必须将它们转换为字节数组,例如使用
Encoding.ASCII.GetBytes

同意-问题实际上很简洁。我没有这样做,所以我无法回答:)使用字符的ref*可能会这样做。这个链接如何:注意,如果它在C中是
char
,在C中就不会是
char
;C
char
是1字节,但是C#
char
是2字节。您仍然没有定义接口。通常argv的长度为argc+1,最后一个条目为NULL。这里是这样吗?你的问题问得不好,也收到了很多不好的建议。它被编译了,我不必更改DllImport签名,但我最终还是得到了PinvokesTack异常。尽管如此,该调用似乎部分有效,因为我看到第三方dll记录到输出窗口。在我接受你的回答之前,我需要确认不是别的原因造成的+目前为1。@Eternal21鉴于PinVokeStackDistancer错误,我猜您是对的,因为它是“字符串数组”,不过查看有关第三方库的更多详细信息会很有帮助。Steve走在正确的道路上,您应该使用封送处理将字符串转换为不安全的指针,但我认为您需要弄清楚这些字符串应该是什么,然后从字符串构建数组。我决定将数据手动“封送”为单字节[]缓冲区。我用我想出的新代码编辑了我的问题。它看起来应该可以工作,但是库不喜欢它,我最终从它那里得到了访问冲突。不确定是否是因为我使用了IntPtr而不是字节**。您的dllimport签名可能是错误的。函数不太可能需要一个C#
char**
,这类似于C中的一个
wchar\u t**
。它可能只是
string[]
,让P/Invoke处理编组,就像在链接的重复问题中一样。函数不需要C#char**,这就是为什么我使用了你建议的字节。但是C#DllImport签名是错误的,因为它使用了C#
字符
。在我的最后一次编辑中,所有这些都修复了。你的评论很有帮助。