繁体   English   中英

将包含StringBuilder的类从C#传递给ada

[英]Passing a class containing a StringBuilder from C# to ada

我在Unity C#中工作,试图与以ada编写的dll集成。 我需要将包含字符串和双精度型的类传递给dll进行修改并返回,但出现以下错误:“传递给非托管代码的Type System.Text.StringBuilder必须具有StructLayout属性。”

现在,这些类已经具有StructLayoutAttribute。 而且我不能将StructLayout属性放在Stringbuilder上,Unity告诉我它仅适用于类和结构。 这使我对错误消息感到非常困惑,因为它似乎在问我一些不可能的事情?

public class controller : MonoBehavior{

    myClass student = new myClass();

    [DllImport ("my_dll", EntryPoint="myFunction@12")]
    public static extern void myFunction(myClass c);

    void Start(){
        myFunction (student);
    }
}

[StructLayoutAttribute(LayoutKind.Sequential, size=2)]
public class myClass {
    public double height = 0.0;
    public System.Text.StringBuilder name = new System.Text.StringBuilder(16);
}

有关此事肯定让人感到有些不适。 如果您的Ada DLL知道如何处理System.Text.StringBuilder,那么这似乎很神奇。 处理本地库时,通常需要传递原始类型。 另外,此Ada DLL可能不是本机dll,而Mono希望使用该dll。 有关封送数据的更多信息,请参见与本地库互操作

现在,假设您的Ada DLL实际上是本机DLL。 它以某种方式知道如何处理StringBuilder。 您可以通过IntPtr将void指针传递到内存地址。 但我高度怀疑这是否行得通。 您最想做的是通过以下方式传递实际的字符串:

public class controller : MonoBehavior{

    myClass student = new myClass();

    [DllImport ("my_dll", EntryPoint="myFunction@12")]
    public static extern void myFunction(myClass c);

    void Start(){
        student.name = "John Doe";
        myFunction (student);
    }
}

[StructLayoutAttribute(LayoutKind.Sequential, size=2)]
public class myClass {
    //The following MarshalAs may be unnecessary.
    [MarshalAs (UnmanagedType.LPStr)]
    public string name;
    public double height = 0.0;
}

LPStr是“指向字符串的长指针”。 假设您的Ada DLL将知道该怎么做。 如果那不起作用,那么您可以删除MarshalAs并查看它是否更喜欢这种方式。

此C函数将采用必须小于约250个字符的输入str,并返回修改后的字符串。 您会看到它分配了一个与sprintf修改后的字符串大小相同的字符串,然后对其进行strcopy分配。 没有相应的free(),因为它将通过mono被释放, 如此处所述。

  char* myFunction(char* input, double height)
  {
    char buffer[256];
    int n = sprintf(buffer, "%s -- %f", input, height);
    char* ret = (char*)malloc(n+1); // +1 for the newline
    strcopy(ret, buffer);
    return ret;
  }

使用PlatformInvoke功能时,默认情况下,IIRC C#将StringBuilder封送为char *。 这很方便与C调用约定DLL进行接口。 一些Ada编译器(尤其是GCC编译器)可能允许Ada库针对C调用约定进行优化。 实际上,这种“几乎神奇的”本质是正确的。 :)

我的建议是:用一个不安全的{}块对Ada函数进行C#调用,并用char()固定住char数组,然后将其传递给Ada函数,然后在返回后再退出固定块。

我没有Visual Studio的工作副本,因此无法验证这一点。

(编辑以修复错误的术语)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM