C# C Dll导入在C中引发Marshall指令异常#
在我的C#项目中包含DLL(用C编写)时,我遇到了一个问题,希望您能帮助我。在我的研究中,我发现了DLLImport,但我不确定C变量转换为哪种类型 我要导入的DLL中的C方法如下所示: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
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语言中再试一次。