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

C# C Dll导入在C中引发Marshall指令异常#,c#,c,pinvoke,marshalling,dllimport,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 *typ

在我的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和inbuf格式的16位Unicode字符字符串 将其转换为一个由16位字符组成的字符串

tableList参数指向翻译表的列表 用逗号分隔

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

typeform参数用于指示斜体、黑体、, 计算机盲文等。它是一个具有相同字符的字符串 长度为*inbuf指向的输入缓冲区。然而,它被使用 要逐字符传回结果,必须有足够的空间 提供以匹配*outlen参数。每个字符表示 输入缓冲区中相应字符的类型。这个 值如下所示:0纯文本;1斜体字;2粗体字;4下划线;8. 计算机盲文。可以将这些值添加到多重强调中。如果 此参数为NULL,未检查类型表单。在里面 此外,如果此参数不为NULL,则在返回时将其设置为have 一个8,在每个位置对应一个字符,其中 定义为具有包含点7、点8或点的点表示 两者,否则为0

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

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);

但最终,最初的爆发根本没有改变。你会说参数是正确的吗?我是否必须以某种方式修改EXBUF参数,因为它是一个StringBuilder,而不仅仅是一个字符串(EXBUF.Replace())?

返回值
Marshallas
是错误的。返回值是
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
的一个新实例,作为
exputf
参数传递。你必须计算出缓冲区需要有多大。我假设函数的文档告诉您如何做。至少对于初始测试,您可以通过
null
对于
typeform
space

null
返回值是
int
而不是字符串应该像错误所说的那样与I4配对。好的,修复了错误,谢谢。Typeform和spacing是最有可能设置为“null”的参数,所以我并不担心这一点。我在使用ref int参数时遇到了更多问题,因为我无法在安全上下文中声明指针以将其用作参数。你有什么办法解决这个问题吗?我添加了描述,这样你就可以知道它是关于什么的。根据我的回答,ref参数很好。元帅将传递指针。至少对于初始测试,您可以通过
typeform
space
null
。关于您的编辑,您没有通过正确的长度参数:
inlength
为4,而
outlength
为30。返回值是多少?您将其分配给了louint。值是多少?好的,我想长度应该是整数的最大长度。如果未遇到错误,lou_translateString函数将返回1;如果无法完成完整的翻译,则返回0。它返回0,显然有问题,但我不知道在哪里。我刚刚把它分配给louint,以便稍后用0或1来测试它。我认为您现在超出了原始问题的范围。我想我已经回答了。如果我是你,我现在将构建一个叫做函数的C++项目。证明其有效,并从等式中删除任何pinvoke互操作问题。一旦你有了一组已知的C++中的参数,在C语言中再试一次。