Marshaling Char*. How to get all characters
I'm trying to create a .net wrapper for a custom COM Interface.
The Interface is defined like this in C++:
DECLARE_INTERFACE_(IDumpAsf, IUnknown)
{
STDMETHOD(get_UserParams) (THIS_
int *is_auto_start,
int *fileSize,
int *packetSize,
char *baseName,
char *filePath
) PURE;
STDMETHOD(set_UserParams) (THIS_
int is_auto_start,
int fileSize,
int packetSize,
char *baseName,
char *filePath
) PURE;
STDMETHOD(enable_Run) (THIS_
bool is_run
) PURE;
};
And I have declared the interface like this in C#:
public interface IDumpASF
{
[PreserveSig]
int get_UserParams(
[Out] out int is_auto_start,
[Out] out int fileSize,
[Out] out int packetSize,
[Out] out System.Sbyte baseName,
[Out] out System.SByte filePath
);
[PreserveSig]
int set_UserParams(
[In] int is_auto_start,
[In] int fileSize,
[In] int packetSize,
[In] string baseName,
[In] string filePath
);
[PreserveSig]
int enable_Run([In] bool a);
}
An exsample of use is this:
int is_auto_start;
int fileSize;
int packetSize;
SByte baseName;
SByte filePath;
IDumpASF dump = (IDumpASF)asfWriter;
dump.get_UserParams(out is_auto_start, out fileSize, out packetSize, out baseName, out filePath);
I'm able to build and run the soulution, but I don't get how I'm suppose to get the all the characters for the baseName and filePath. When I send the SByte, it get the first character back, but how do I get the rest? I have tried several other types like Sbyte[], String, StringBuilder and IntPtr. Whenever I try to convert them into a string, I get an 开发者_JAVA技巧AccessViolationException.
I bet there is some silly thing I have missed, but my patients is wearing thin here.
Any help would be much appriciated!
-Svein
You have to declare the argument as StringBuilder, don't use out. Be sure to initialize the string builder you pass properly, you have to set its Capacity high enough so that this native code cannot destroy the garbage collected heap. Fixing the COM code would be something to consider since it is so fundamentally unsafe, it really should use a BSTR.
Thank you for you answer. After some more trial and error, I finally got the right setup. As you said, I should use StringBuilder without [Out]. My problem was that the values I got back didn't make much sense. In addition to what you told me, I also had to specify how to marshal the value with the MarshalAs attribute.
Thanks alot for your help!
This is what the test class looks like:
System.Text.StringBuilder baseName = new System.Text.StringBuilder(256);
System.Text.StringBuilder filePath = new System.Text.StringBuilder(256);
EncirisWrapper.IDumpASF dump = (EncirisWrapper.IDumpASF)asfWriter;
dump.get_UserParams(out is_auto_start, out fileSize, out packetSize, baseName, filePath);
And this is how the wrapper looks:
[PreserveSig]
int get_UserParams(
[Out] out int is_auto_start,
[Out] out int fileSize,
[Out] out int packetSize,
[MarshalAs(UnmanagedType.LPStr)] System.Text.StringBuilder baseName,
[MarshalAs(UnmanagedType.LPStr)] System.Text.StringBuilder filePath
);
-Svein
精彩评论