Only first character is passed in pinvoke string - dll

I have a c++ dll that I am using using Pinvoke.
The method signature is as follow:
c++:
EXTERN_C BOOL std_call MyCppMethod(LPCSTR param1, LPCSTR param2);
C#:
[DllImport("MyDll.dll", CharSet = CharSet.Unicode, SetLastError = true)]
public static extern bool MyCppMethod(
/*[MarshalAs(UnmanagedType.LPWStr)]*/ string param1,
/*[MarshalAs(UnmanagedType.LPWStr)]*/ string param2
);
for technical reasons I replaced the dll with a lib, and wrapped the lib with a dll that uses EXPORTS.def file and EXPORTS declaration to export the method from the lib.
Since I have dine that I see a weird behavior. instead of getting the string in the method implementation I get only the first character.
I had tried to replace the calling convention, to use marshalAs LPCWSTR, and also tried to replace the lpcstr in the c++ decleration with char*.
non of the above helped me to solve the problem and I still get only the first character.
Why this is happening and how can I solve this problem?

LPCSTR is a pointer to null-terminated array of char, and UnmanagedType.LPWStr is a pointer to null-terminated array of wchar_t. So there is a simple mis-match.
The reason why you only received a single character is that ASCII characters, when represented as two byte UTF-16 characters, have the ASCII value in one byte, and a zero in the other byte. When interpreted as null-terminated array of char, this is a string of length one. The zero byte is interpreted as the null-terminator.
You can fix it by changing either:
LPCSTR to LPCWSTR on the native side, or
UnmanagedType.LPWStr to UnmanagedType.LPStr on the managed side.
Frankly, to me it makes more sense to use Unicode these days so I would go for option 1. Indeed, since you specified CharSet.Unicode then there is no need for the MarshalAs at all. The code would look like this:
C++
BOOL std_call MyCppMethod(LPCWSTR param1, LPCWSTR param2);
C#
[DllImport("MyDll.dll", CharSet = CharSet.Unicode)]
public static extern bool MyCppMethod(string param1, string param2);
Note that I am also sceptical of your setting SetLastError to true. Does your function really call SetLastError?

Related

Equality operator, Equals, GetHashCode for const objects in C++ cli

I have created a new managed, reference class in C++ cli. And now I want to overload equality of objects of this class.
public ref class DerivedFromObject {
virtual bool Equals(Object^ obj) override;
virtual int GetHashCode() override;
static bool operator!= (const DerivedFromObject%, const DerivedFromObject%);
static bool operator== (const DerivedFromObject%, const DerivedFromObject%);
}
As far as I know from C#, operator!= calls operator==, that calls Equals, which refers to GetHashCode.
bool DerivedFromObject::operator==(const DerivedFromObject % a, const DerivedFromObject % b)
{
a.Equals((Object^)%b); // Error
}
In the snippet above, Equals and GetHashCode cannot be called on a const object, that's why I cannot call Equals from operator==.
How can I mark method that doesn't change the object in C++ cli? Or What the most appropriative way to define equality chain?
There's two things here:
.Net doesn't really have the concept of const in the way that C++ does. C++/CLI will enforce the rules that C++ has, but since .Net doesn't use it, no library methods are declared const, so you'll have problems calling just about any method. Rather than being explicitly declared like in C++, it's just by convention that methods like equals don't modify their parameters.
Since you used const%, I think you were trying to parallel the C++ convention of passing const& parameters. % is more similar in usage to ** double pointer than to &: You pass things parameters as % (or ^% for reference types) when the method can assign a value to the parameter, and it should be available to the calling method.
Here's how I would implement this:
public ref class DerivedFromObject : IEquatable<DerivedFromObject> {
virtual bool Equals(DerivedFromObject^ other);
virtual bool Equals(Object^ obj) override;
virtual int GetHashCode() override;
static bool operator!= (DerivedFromObject^, DerivedFromObject^);
static bool operator== (DerivedFromObject^, DerivedFromObject^);
}
One other thing you said:
...Equals, which refers to GetHashCode.
Be careful here, because it is possible for unequal objects to have the same hash code.
GetHashCode will need to evaluate everything, and then if the hash codes are equal, then Equals need to evaluate everything again to be sure they're actually equal. It'll probably be more efficient to not look at the hash code, just compare the objects field by field, and bail out as soon as they're not equal.

Const from function

How can such a function be created? (How do the framework do it for Chr)
Or why is it not possible, but possible in the framework?
Example of consts declared from function:
''' <summary>Carriage Return \r 13 0xD</summary>
Public Const Cr As Char = ChrW(&HD)
''' <summary>Line Feed \n 10 0xA</summary>
Public Const Lf As Char = ChrW(&HA)
MS reference source for ChrW
So it should be possible to create similar functions ex:
Public Const Magic As String = "Magic" ' ok
Public Const lcMagic As String = Magic.ToLower ' not ok - wanted to avoiding potential bugs if Magic is ever changed.
Public Const Magic2 As String = functionGeneratingLongButStaticString()
A workaround for most cases is something like:
''' <summary>Lowercase value of Magic</summary>
Public Shared ReadOnly lcMagic As String = Magic.ToLower
But this do not provide intellisense of the actual value.
And not "secure" since it is possible to modify ReadOnly fields with reflection
So is there any way to declare 'const functions' at all, and if not, how do the framework really do it?
Edit:
Checked the generated IL:
.field public static literal char Cr = char('\r')
Which means it is a special case for the compiler.
The compiler may be treating AscW and ChrW as special cases. A search of the Roslyn source code for "AscW" turns up the following in OptimizeLibraryCall (lots of code snipped for clarity):
' AscW(char) / AscW(String)
' all values can be optimized as a literal, except an empty string that produces a diagnostic
If IsWellKnownTypeMember(WellKnownMember.Microsoft_VisualBasic_Strings__AscWCharInt32, method) OrElse
IsWellKnownTypeMember(WellKnownMember.Microsoft_VisualBasic_Strings__AscWStringInt32, method) Then
'[...]
Return ConstantValue.Create(AscW(argumentValue))
End If
' ChrW
' for -32768 < value or value > 65535 we show a diagnostic
If IsWellKnownTypeMember(WellKnownMember.Microsoft_VisualBasic_Strings__ChrWInt32Char, method) Then
'[...]
Return ConstantValue.Create(ChrW(argumentValue))
End If
'[...]
There's also a comment in EarlyWellKnownAttributeBinder.CanBeValidAttribute that specifically mentions AscW and ChrW in the types of compile-time constants that can be used for attribute values:
' 11.2 Constant Expressions
'
'A constant expression is an expression whose value can be fully evaluated at compile time.
' [...]
' The following run-time functions:
' Microsoft.VisualBasic.Strings.ChrW
' Microsoft.VisualBasic.Strings.Chr, if the constant value is between 0 and 128
' Microsoft.VisualBasic.Strings.AscW, if the constant string is not empty
' Microsoft.VisualBasic.Strings.Asc, if the constant string is not empty
The Mono vbnc compiler seems to have an IsConstantMethod helper method to support these functions (it specifically checks whether the method is AscW, Asc, ChrW, or Chr), along with a test case specifically to test whether const statements accept those functions, which suggests they are special cases.
If you look at your compiled assembly in ildasm, you'll see:
.field public static literal char Cr = char(0x000D)
You can see that the compiler is evaluating the function and emitting the result -- it's not embedding any sort of "constant function" call, and there's not any sort of attribute decoration on those functions in the reference source that marks them as a "constant function".
So to answer your questions, it looks like the compiler does this by treating those string functions as special hardcoded cases, and it doesn't look like there's any way to do so, short of modifying the compiler code.
From MSDN:
You cannot use variables or functions in initializer. However, you can use conversion keywords such as CByte and CShort. You can also use AscW if you call it with a constant String or Char argument, since that can be evaluated at compile time.
ChrW etc are special because the compiler is designed to allow them:
Private Const vblf As String = ChrW(10)
Compiles to:
private const char vblf = '\n';
Most other forms using NET function are illegal:
Private Const vbcr As String = Convert.ToString(New Byte() {13})
Private Const vblf2 As Char = Environment.NewLine
Private Const Z As String = Ziggy.ToLower
Even if Ziggy is a constant, making it seem like it should be legal, the function result is not. The return could be different on a non-English system making for very nasty issues at runtime when strings do not match but should.

A call to PInvoke function 'ABC' has unbalanced the stack.

I have a C# application (x86 .net 3.5 on Windows 7 vs2010) which call a C function
when I upgrade it to .net 4, I got the following message:
This is likely because the managed PInvoke signature does not match the unmanaged target signature. Check that the calling convention and parameters of the PInvoke signature match the target unmanaged signature.
C signature:
BOOL ABC( UDF_HANDLE handle, char* pQualifiedName )
//#define UDF_HANDLE void*
C# side:
[SecuritySafeCritical]
[DllImport(dllPath, CharSet = CharSet.Unicode, CallingConvention = CallingConvention.StdCall, ThrowOnUnmappableChar = true)]
internal static extern int ABC(
[In] IntPtr handle,
[MarshalAs(UnmanagedType.LPStr)] string qualifiedName);
Any help appreciated.
I redefined ABC first parameter to be same as the first parameter in the function.
The C++ code uses the cdecl calling convention. But you've specified stdcall in your p/invoke. Change that in the C# code and your two declarations will match.

How to convert from _bstr_t to System::String

Firstly, I'm some what new to C++/CLI.
After doing some research I've found that I can use Marshal::PtrToStringBSTR to convert an IntPtr to System::String. So, is there a way to convert my _bstr_t variable to an IntPtr so that I can pass it to the function mentioned and do conversion?
Or,
What is the correct way of converting a _bstr_t variable to System::String?
System::String has a constructor that takes a wchar_t*. Which makes this code work:
_bstr_t bs(L"Hello world");
String^ ss = gcnew String(bs.GetBSTR(), 0, bs.length());
Passing the length() ensures that embedded zeros are properly handled. If you don't care about that then you can simply use gcnew String(bs.GetBSTR());
You should be able to use marshal_as to get a System::String.
marshal_as<System::String^>(value);
Here's the MSDN page for the different string types: http://msdn.microsoft.com/en-us/library/bb384865.aspx
Most important thing is to pay attention to the right #include depending on your string type.
I managed to find a solution through the way I mentioned itself, by using Marshal::PtrToStringBSTR. This is what I did:
void SomeFunction( String^% str )
{
_bstr_t bs(L"Hello world");
str = Marshal::PtrToStringBSTR(
static_cast<IntPtr>( bs.GetAddress()));
}

Pass an argument by reference in C++/CLI so re-assignment affects the caller

Probably this is not a difficult question, but I am always a little bit confused on how to treat String type as an argument in Visual C++. I have the following to functions:
void function_1(String ^str_1)
{
str_1 = gcnew String("Test");
}
void function_2()
{
String ^str_2 = nullptr;
function_1(str_2);
}
After calling function_1, str_2 is still equal to null, but what I want to achieve is that str_2 is equal to Test. So, how can I achieve that the content of str_1 is passed to function_2?
Thanks for any advice.
Use a tracking reference:
void function_1(String ^%str_1)
{
str_1 = gcnew String("Test");
}
Explanation: Passing String ^ is like passing a pointer. Changes are only made to the local copy of the reference. String ^% is like passing a reference to a reference... just as you would pass a pointer to a pointer when calling a function that should change the original pointer.