Reputation: 9506
I have this native interface:
void CLASS_Version(char *Version);
I tried to import it with:
[DllImport("class.dll", EntryPoint = "CLASS")]
private static extern void CLASS_Version(ref string[] Version);
or
[DllImport("class.dll", EntryPoint = "CLASS")]
private static extern void CLASS_Version(ref char[] Version);
[DllImport("class.dll", EntryPoint = "CLASS")]
private static extern void CLASS_Version(out string[] Version);
[DllImport("class.dll", EntryPoint = "CLASS")]
private static extern void CLASS_Version(out char[] Version);
But I alway get "AccessViolation" error, The only good run was made with
[DllImport("class.dll", EntryPoint = "CLASS")]
private static extern void CLASS_Version(ref char Version);
but this way I got only the first char of the strings... how to get all string?
Upvotes: 0
Views: 388
Reputation: 63752
char *
is ambiguous, but it definitely isn't an array of strings. Most likely, it's a pointer to a string, so you'll use just a simple StringBuilder
(no ref
or out
).
Also, make sure to use the proper marshalling attributes. .NET strings are always widechars, unlike your signature.
In general, a signature of a function isn't enough for proper interop with native code. You need to understand the meaning of the arguments and the return values, and you need to know the calling convention. You need to read the documentation, in other words :)
Upvotes: 4
Reputation: 4082
Sadly the answer cannot be determined by type alone. If it were that simple there would be parsers that could write the native wrapper for you. The type you have to use depends on what the function is actually doing.
In your case the char *
is not marked const
, and it is being accepted as a parameter, which implies that it's intended to be a user-allocated area of memory available for the function to write to. As there is no size parameter, there is most likely a maximum size that the version string can be, which should be indicated in the documentation of the code.
Given that this is string handling, you also have to worry about the encoding. For the sake of simplicity I'm going to assume (and hope) your string is in ASCII/Windows-1252 and not UTF8, UTF7 or some other format.
Given these assumptions, you have several options, but I will be presenting just the preferred way of handling this based on the information provided. (It may be that your situation requires something different, but this is the best solution I can suggest based on asumptions inferred from the information in your question.)
[DllImport("class.dll", EntryPoint = "CLASS_Version", , CharSet = CharSet.Ansi)] // CharSet is important
private static extern void CLASS_Version(StringBuilder Version);
This is the 'correct' way to manage the situation - rely on the compiler to handle the marshalling for you. One small caveat however is that you must manually set the capacity of the StringBuilder before passing it to the method.
// be sure to allocate a correct size,
// there will be no error if it overflows because it's too small
StringBuilder buffer = new StringBuilder(size);
// automagically marshalled to and from unmanaged code byt the compiler
CLASS_Version(buffer);
string version = buffer.ToString();
I'd like to take this opportunity to point out that CLASS_Version
shouldn't be private
. All your native methods should be made public
and grouped together in one internal static class
.
Some additional resources about string marshalling that you may find handy: https://limbioliong.wordpress.com/2011/11/01/using-the-stringbuilder-in-unmanaged-api-calls/
Upvotes: 0
Reputation: 1667
try this:
[DllImport("class.dll", EntryPoint = "CLASS")]
private static extern void CLASS_Version([MarshalAs(UnmanagedType.VBByRefStr)] ref string Version);
And when you are going to call your method:
Version = Space(14);// first declare memory space requiered ¿14 bytes? ¿more?
CLASS_Version(Version);
Upvotes: 0
Reputation: 26496
Basically pointers are represented with IntPtr
type.
plus, the entry point should be the string representing the function name
try:
[DllImport("class.dll", EntryPoint = "CLASS_Version")]
private static extern void CLASS_Version(IntPtr Version);
Upvotes: 0