简体   繁体   中英

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. The DLL was written with Clarion, and I'm not very familiar with the data types being used. 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. 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.

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. The version parameter in question is declared as type cstring* not cstringt*. And in Clarion, cstringt*. And in Clarion, cstring` is apparently just a c-style, null-terminated string. So the marshalling shouldn't be that complicated, since they claim it was written with C calling conventions. Has anyone successfully p/invoked a Clarion DLL that passes strings via a reference param?

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:

[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):

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:

SCODE WINAPI Test( const CString& str );

I used the following C# code to import:

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

And this C# code to call:

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:

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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