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()));
}
Related
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?
This apparently is a Google-proof term since I can't get any search engines to not throw away the "extra" characters. I did also look on MSDN in the C++ reference but I can't seem to find the C++/CLI reference because there is nothing in the declarations section on it.
It means "pass by reference":
void bar::foo(Object^% arg) {
arg = gcnew Object; // Callers argument gets updated
}
Same thing in C++:
void foo(Object** arg) {
*arg = new Object;
}
or C#:
void foo(out object arg) {
arg = new Object();
}
C++/CLI doesn't distinguish between ref and out, it does not have the definite assignment checking feature that the C# language has so no need to distinguish between the two. Same in VB.NET, ByRef vs ByVal.
% is a tracking reference.
It is similar to a native reference (Object&), but a tracking reference can reference a CLR object while a native reference cannot. The distinction is necessary because the garbage collector can move CLR objects around, so a CLR-object's memory address may change.
The ^ is a handle. This simply means it is managed. See MSDN and also this SO post.
Essentially, it's the "managed" version of Object*&, and equivalent to ref or out on a reference type in C#.
This is a managed pointer by reference. So if you had something like:
void DoSomething(System::String^% stringObject)
in C# it would look like:
void DoSomething(ref System.String stringObject)
This is a C++/CLI Tracking Reference. This is kind of like a C++ reference, but to a managed object.
I guess this will be simple for C++/CLI gurus.
I am creating a wrapper which will expose high-performance C++ native classes to C# WinForms application.
Everything went fine with simple known objects and I could wrap also a callback function to delegate. But now I am a bit confused.
The native C++ class has a following method:
int GetProperty(int propId, void* propInOut)
At first I thought I could use void* as IntPtr, but then I found out that I need to access it from C#. So I thought about a wrapper method:
int GetProperty(int propId, Object^ propInOut)
but as I looked through the C++ source, I found out that the method needs to modify the objects. So obviously I need:
int GetProperty(int propId, Object^% propInOut)
Now I cannot pass Objects to native methods so I need to know how to treat them in the wrapper. As the caller should always know what kind of data he/she is passing/receiving, I declared a wrapper:
int GetProperty(int propId, int dataType, Object^% propInOut)
I guess, I can use it to pass reference and value types, for example, an int like this:
Object count = 100; // yeah, I know boxing is bad but this will not be real-time call anyway
myWrapper.GetProperty(Registry.PROP_SMTH, DATA_TYPE_INT, ref count);
I just added a bunch of dataType constants for all the data types I need:
DATA_TYPE_INT, DATA_TYPE_FLOAT, DATA_TYPE_STRING, DATA_TYPE_DESCRIPTOR, DATA_TYPE_BYTE_ARRAY
(DATA_TYPE_DESCRIPTOR is a simple struct with two fields: int Id and wstring Description - this type will be wrapped too, so I guess marshaling will be simple copying data back and forth; all the native strings are Unicode).
Now, the question is - how to implement the wrapper method for all these 5 types?
When I can just cast Object^% to something (is int, float safe to do that?) and pass to native method, when do I need to use pin_ptr and when I need some more complex marshaling to native and back?
int GetProperty(int propId, int dataType, Object^% propInOut)
{
if(dataType == DATA_TYPE_INT)
{
int* marshaledPropInOut = ???
int result = nativeObject->GetProperty(propId, (void*)marshaledPropInOut);
// need to do anything more?
return result;
}
else
if(dataType == DATA_TYPE_FLOAT)
{
float* marshaledPropInOut = ???
int result = nativeObject->GetProperty(propId, (void*)marshaledPropInOut);
// need to do anything more ?
return result;
}
else
if(dataType == DATA_TYPE_STRING)
{
// will pin_ptr be needed or it is enough with the tracking reference in the declaration?
// the pointers won't get stored anywhere in C++ later so I don't need AllocHGlobal
int result = nativeObject->GetProperty(propId, (void*)marshaledPropInOut);
// need to do anything more?
return result;
}
else
if(dataType == DATA_TYPE_BYTE_ARRAY)
{
// need to convert form managed byte[] to native char[] and back;
// user has already allocated byte[] so I can get the size of array somehow
return result;
}
else
if(dataType == DATA_TYPE_DESCRIPTOR)
{
// I guess I'll have to do a dumb copying between native and managed struct,
// the only problem is pinning of the string again before passing to the native
return result;
}
return -1;
}
P.S. Maybe there is a more elegant solution for wrapping this void* method with many possible datatypes?
It doesn't necessarily make sense to equate a C# object to a void*. There isn't any way to marshal arbitrary data. Even with an object, C# still knows what type it is underneath, and for marshaling to take place -- meaning a conversion from the C++ world to C# or vice-versa -- the type of data needs to be known. A void* is just a pointer to memory of a completely unknown type, so how would you convert it to an object, where the type has to be known?
If you have a limited number of types as you describe that could be passed in from the C# world, it is best to make several overloads in your C++/CLI code, each of which took one of those types, and then you can pin the type passed in (if necessary), convert it to a void*, pass that to your C++ function that takes a void*, and then marshal back as appropriate for the type.
You could implement a case statement as you listed, but then what do you do if you can't handle the type that was passed in? The person calling the function from C# has no way to know what types are acceptable and the compiler can't help you figure out that you did something wrong.
So I've run into a case where I have a class that can store either a string or a numeric value, and I want a single property to return one or the other (it would be a failure for both to be set). I'm using a custom generic class to deal with the numerics (so I can use signed, unsigned, and nullables), and will be storing the string in a separate variable.
In theory, if overloading could be done based on the return type, I could do this quite easily. But .NET currently disallows this. So I am wondering if there is some other really-far-out-there trick (outside of MSIL generation via Reflection.Emit) that could accomplish the same thing.
I'm open to ideas via delegates, pointer dereferencing, generics, mystical rites, etc. Also interested in any thoughts or pros/cons of such possibilities as a learning tool. If using a standard Object is the only way to achieve what I want, then that's fine with me. But It's difficult to find the correct set of keywords to hunt down this kind of capability on Google, so I thought I'd ask here before I moved on to doing something else on the project.
I don't see how using anything other than Object would work, for a simple property. Imagine you're the caller - what would you expect the declared type of the property to be? What type of value would you try to assign the expression to?
If you really have to have a single property which can return various different types, Object sounds like the way to go.
You can have the public property as string and also return the number after converting it to string.
public string YourProperty
{
get {
if(somecondition)
return "some string";
else if(someothercondition)
return 1234.ToString();
}
}
while accessing your property you can use Convert.ToInt32().
Example:
public void YourMethod()
{
int a;
string str;
bool isNumber;
try
{
a = Convert.ToInt32(obj.YourProperty);
isNumber = true;
}
catch(FormatException e)
{
str = obj.YourProperty;
isNumber = false;
}
}
Though this is not a good way programming, but you will acheive your objective of using only one property for both string and number.
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.