C Dll Import在C#中抛出Marshall指令异常

时间:2013-12-31 12:49:09

标签: c# c pinvoke marshalling dllimport

我的C#项目中有一个包含DLL(用C语言编写)的问题,希望你能帮到我。在我的研究中,我发现了DLLImport,但我不确定C变量转换为哪种类型......

我要导入的DLL中的C方法如下:

int lou_translateString (
     const char * tableList,
     const widechar * inbuf,
     int *inlen,
     widechar *outbuf,
     int *outlen,
     char *typeform,
     char *spacing,
     int mode);

这是我试过的DLLImport:

[DllImport("liblouis-2.dll", EntryPoint = "lou_translateString", CharSet = CharSet.Ansi, ExactSpelling = true)]
    [return: MarshalAs(UnmanagedType.LPStr)]
    public static extern int translate([MarshalAs(UnmanagedType.LPStr)]
        String tableList,
        String inbuf,
        int inlen,
        String outbuf,
        int outlen,
        String typeform,
        String spacing,
        int mode);

但是当我尝试调用我得到的方法时:

MarshallDirectiveException 无法封送“返回值”:无效的托管/非托管类型组合 (Int32 / UInt32必须与I4或U4配对)

任何人都可以帮忙解决这个问题吗?我很确定它与方法中的参数类型有关,但我不知道如何正确地声明它们。任何帮助将不胜感激!

提前致谢 亚历

添加了简短的文档以进行说明

  

此函数在inbuf和中使用一串16位Unicode字符   在outbuf中将其转换为一个16位字符串。

     

tableList参数指向转换表列表   以逗号分隔。

     

请注意,* inlen和* outlen参数都是指针   整数。调用该函数时,这些整数包含   最大输入和输出长度。当它返回时,它们   设置为实际使用的长度。

     

typeform参数用于表示斜体类型,粗体字型,   电脑盲文等。它是一串相同的字符   length作为* inbuf指向的输入缓冲区。但是,它被使用   传回逐个字符的结果,所以必须有足够的空间   提供匹配* outlen参数。每个字符表示   输入缓冲区中相应字符的typeform。该   值如下:0纯文本; 1斜体; 2大胆; 4下划线; 8   电脑盲文。可以添加这些值以进行多次强调。如果   此参数为NULL,不检查类型表单。在   另外,如果此参数不为NULL,则返回时设置为   每个位置的8对应于outbuf中的一个字符   定义为包含点7,点8或点的点表示   两者,否则为0。

     

间距参数用于指示间距的差异   输入字符串和已翻译的输出字符串之间。也是   与* inbuf指向的字符串长度相同。如果这   参数为NULL,不计算间距信息。

     

mode参数指定应如何进行翻译。

     

如果没有遇到错误,则函数返回1,如果是,则返回0   无法完成翻译。

这是我在Main中测试函数所写的内容:

        StringBuilder outbuf = new StringBuilder("Test", 30);
        int inlength = 100;
        int louint = 0;
        int outlength = 100;
        String inbuf = "test";


        louint = lou_translateString("de-de-g1.ctb", inbuf, inlen: ref inlength, outbuf: outbuf, outlen: ref outlength, typeform: null, spacing: null, mode: 8);

但最后原来的outbuf根本没有改变。你会说参数是对的吗?我是否必须以某种方式修改outbuf参数,因为它是一个StringBuilder而不仅仅是一个String(outbuf.Replace())?

1 个答案:

答案 0 :(得分:2)

返回值MarshalAs错误。返回值为int而不是字符串。这解释了错误,但还有更多。你的pinvoke声明的其余部分有错误。我会这样做:

[DllImport("liblouis-2.dll", CharSet = CharSet.Unicode)]
public static extern int lou_translateString(
    [MarshalAs(UnmanagedType.LPStr)]
    string tableList,
    string inbuf,
    ref int inlen,
    StringBuilder outbuf,
    ref int outlen,
    [MarshalAs(UnmanagedType.LPStr)]
    StringBuilder typeform,
    [MarshalAs(UnmanagedType.LPStr)]
    StringBuilder spacing,
    int mode
);

必须将从函数编组的文本缓冲区声明为StringBuilder。你还有其他一些错误。将int*翻译为ref int

为了调用该函数,您需要创建一个StringBuilder的新实例作为outbuf参数传递。你必须弄清楚缓冲区需要多大。我假设该函数的文档告诉您如何执行此操作。至少在初始测试中,您可以null传递typeformspacing