c# - C Dll 导入在 C# 中引发 Marshall 指令异常

标签 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)

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

提前致谢 亚历克斯

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

This function takes a string of 16-bit Unicode characters in inbuf and translates it into a string of 16-bit characters in outbuf.

The tableList parameter points to a list of translation tables separated by commas.

Note that both the *inlen and *outlen parameters are pointers to integers. When the function is called, these integers contain the maximum input and output lengths, respectively. When it returns, they are set to the actual lengths used.

The typeform parameter is used to indicate italic type, boldface type, computer braille, etc. It is a string of characters with the same length as the input buffer pointed to by *inbuf. However, it is used to pass back character-by-character results, so enough space must be provided to match the *outlen parameter. Each character indicates the typeform of the corresponding character in the input buffer. The values are as follows: 0 plain-text; 1 italic; 2 bold; 4 underline; 8 computer braille. These values can be added for multiple emphasis. If this parameter is NULL, no checking for type forms is done. In addition, if this parameter is not NULL, it is set on return to have an 8 at every position corresponding to a character in outbuf which was defined to have a dot representation containing dot 7, dot 8 or both, and to 0 otherwise.

The spacing parameter is used to indicate differences in spacing between the input string and the translated output string. It is also of the same length as the string pointed to by *inbuf. If this parameter is NULL, no spacing information is computed.

The mode parameter specifies how the translation should be done.

The function returns 1 if no errors were encountered and 0 if a complete translation could not be done.

这是我为了测试 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 而不仅仅是一个字符串 ( outbuf.Replace() )?

最佳答案

返回值 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 参数传递。您必须计算出缓冲区需要多大。我假设该函数的文档会告诉您如何执行此操作。至少对于初始测试,您可以为 typeformspacing 传递 null

关于c# - C Dll 导入在 C# 中引发 Marshall 指令异常,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20857649/

相关文章:

c# - sql中已经求和的列的总和

c# - 在 RabbitMQ 中混合 Pub/Sub 和工作队列

c# - pInvoke C# DLL导入问题

c - 服务器提示符下的文件输入

c - 其他信任中结构动态数组的 Valgrind 错误

c#调用方法使用P/Invoke导致AccessViolation Exception

c# - WTSQueryUserToken 在 C# 的 Windows 7 上总是抛出 "An attempt was made to reference a token that does not exist"

c# - 针对 WPF 和 Dispatcher 的 NMock 问题测试

c# - vtables是如何在c++和c#中实现的?

无法弄清楚seg错误的原因是什么