简体   繁体   English

如何通过P / Invoke封送cstring *?

[英]How do I marshal cstring* via P/Invoke?

I'm attempting to call a 3rd-party DLL from C#, and I'm having trouble marshalling some string data. 我试图从C#调用第三方DLL,但无法整理一些字符串数据。 The DLL was written with Clarion, and I'm not very familiar with the data types being used. DLL是用Clarion编写的,我对所使用的数据类型不是很熟悉。 Specifically, the spec has this signature for a function that I can't get to work: 具体来说,该规范具有我无法使用的功能的以下签名:

Bool QuerySoftwareVersion( cstring* version)  // edited documentation typo
//Returns Software version (20 character cstring).  

I was assuming that the cstring was just a null-terminated string, but I wasn't able to get it to work with out char[] version in my definition. 我以为cstring只是一个以空字符结尾的字符串,但是在我的定义中,我无法使它与out char[] version一起使用。 Anyone know the right way to handle this? 有人知道正确的处理方式吗?

EDIT: Actually, what I've found thus far suggests that a cstring in Clarion is indeed just a null-terminated string. 编辑:实际上,到目前为止,我发现这表明Clarion中的cstring确实只是一个以空字符结尾的字符串。

UPDATE: I've updated the title of the question and the details because it turns out that there was a typo in the DLL documentation. 更新:我已经更新了问题的标题和详细信息,因为事实证明DLL文档中有错字。 The version parameter in question is declared as type cstring* not cstringt*. And in Clarion, 有问题的version参数声明为cstring*类型,而不是cstringt*. And in Clarion,类型cstringt*. And in Clarion, cstringt*. And in Clarion, cstring` is apparently just a c-style, null-terminated string. cstringt*. And in Clarion, cstring`显然只是一个c样式,以null终止的字符串。 So the marshalling shouldn't be that complicated, since they claim it was written with C calling conventions. 因此,封送处理不应该那么复杂,因为他们声称封送处理是使用C调用约定编写的。 Has anyone successfully p/invoked a Clarion DLL that passes strings via a reference param? 有没有人成功地p /调用了通过参考参数传递字符串的Clarion DLL?

I've never called into Clarion, but I've got a DLL (in C) that is called from both Clarion and C#, and I'd interop that as: 我从未调用过Clarion,但是我有一个Clarion和C#都调用过的DLL(用C语言编写),我将其互操作为:

[DllImport("clarionlib.dll", CharSet=CharSet.Ansi,
CallingConvention = CallingConvention.Cdecl,
ExactSpelling=true, EntryPoint="QuerySoftwareVersion")] static extern
            bool QuerySoftwareVersion(StringBuilder sName);

Note also that the StringBuilder parameter you pass has to be sized up to the maximum expected return size (pardon my C#, I'm sure there's a shorter equivalent): 还要注意,您传递的StringBuilder参数的大小必须达到最大预期返回值的大小(请原谅我的C#,我敢肯定等效项会更短):

System.Text.StringBuilder buffer;
buffer = new System.Text.StringBuilder();
buffer.EnsureCapacity(21);
QuerySoftwareVersion(buffer);
string myString = buffer.ToString();

I had some success with a CString reference in a DLL API: 我在DLL API中使用CString引用取得了一些成功:

SCODE WINAPI Test( const CString& str );

I used the following C# code to import: 我使用以下C#代码导入:

[DllImport("CBData.Dll")]
public static extern int Test( [MarshalAs(UnmanagedType.LPStr)] ref String str );

And this C# code to call: 并调用以下C#代码:

String b = "Some text";
int x = Test(ref b);

This worked for me - I am not sure if this is safe though. 这对我有用-我不确定这是否安全。 I hope this helps you. 我希望这可以帮助你。

Try with a StringBuilder: 尝试使用StringBuilder:

[DllImport("mylibrary.dll")]
static extern bool QuerySoftwareVersion([Out] StringBuilder version);

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

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