I have C# sample application with code
SampleClass cls = new SampleClass();
byte[] b = new byte[] { 1, 2, 3 };
object obj = b;
cls.Send(obj);
SampleClass is seperate dll which is implemented using Managed C++(CLI).
Now in Send method i am doing following.
void Send(Object^ data)
{
cli::array<System::Byte>^ b = data; //it is giving error
}
How can i convert Object^ to cli::array^?
cli::array<System::Byte>^ b = data; //it is giving error
It is a compile error. That statement is not valid in C++/CLI, just like it is never valid in C#. And you solve it the same way as you do in C#, you must use a cast to make the conversion.
That rule isn't there just to make your life difficult, a conversion like this is very risky and apt to throw an InvalidCastException. Having to use a cast operator alerts the reader, helps you debug the program and convinces the compiler that you know what you're doing.
Casting managed object references in C++/CLI is done with the safe_cast<> keyword. Fix:
auto b = safe_cast<cli::array<System::Byte>^>(data);
Related
I am trying to understand lambda functions better and would like some example of how I could add to a vector while converting System.String^ to std::string with such a Lambda example (If I am able to).
My current foreach:
List<String^>^ names = //Returning 'System.String' List from C#
for each (System::String^ name in names)
{
std::string convertedString = msclr::interop::marshal_as< std::string >(name);
nameObjects.push_back(MyObject(convertedString, "test"));
}
But I would like to extend it to something like this (My best guess but I am missing the logic to convert each element of "names" to a single string, this is where a Lambda would help me):
std::vector<nameObjects> testObjects{ std::begin(msclr::interop::marshal_as< std::string >(names)), std::end(msclr::interop::marshal_as< std::string >(names)) };
Alright, I figured out a way to make this work...it requires using the obscure cliext classes.
First, create a cliext::vector, there is an overload with takes an IEnumerator.
cliext::vector<String^> v_names(names);
Now, you can use cliext::transform() (not std::transform) to do STL-style iteration, and create MyObject instances with a lambda
std::vector<MyObject> testObjects;
cliext::transform(v_names.begin(), v_names.end(), std::back_inserter(testObjects), [](String^ name)
{
std::string convertedString = msclr::interop::marshal_as< std::string >(name);
return MyObject(convertedString, "test");
});
I have a list of KeyValuePairs. I normally would use ToDictionary.
However I just noted that the error message (shown below) has something about explicit cast, which implies I can actually cast the list to Dictionary<...>. How can I do this?
Cannot implicitly convert type 'System.Linq.IOrderedEnumerable<System.Collections.Generic.KeyValuePair<int,string>>' to 'System.Collections.Generic.Dictionary<int, string>'. An explicit conversion exists (are you missing a cast?)
Sample code:
Dictionary<int, string> d = new Dictionary<int, string>() {
{3, "C"},
{2, "B"},
{1, "A"},
};
var s = d.OrderBy(i => i.Value);
d = s;
Implies I can actually cast list to dictionary
Well, it implies that the cast would be valid at compile-time. It doesn't mean it will work at execution time.
It's possible that this code could work:
IOrderedEnumerable<KeyValuePair<string, string>> pairs = GetPairs();
Dictionary<string, string> dictionary = (Dictionary<string, string>) pairs;
... but only if the value returned by GetPairs() were a class derived from Dictionary<,> which also implemented IOrderedEnumerable<KeyValuePair<string, string>>. It's very unlikely that that's actually the case in normal code. The compiler can't stop you from trying, but it won't end well. (In particular, if you do it with the code in your question and with standard LINQ to Objects, it will definitely fail at execution time.)
You should stick with ToDictionary... although you should also be aware that you'll lose the ordering, so there's no point in ordering it to start with.
To show this with the code in your question:
Dictionary<int, string> d = new Dictionary<int, string>() {
{3, "C"},
{2, "B"},
{1, "A"},
};
var s = d.OrderBy(i => i.Value);
d = (Dictionary<int, string>) s;
That compiles, but fails at execution time as predicted:
Unhandled Exception: System.InvalidCastException: Unable to cast object of type 'System.Linq.OrderedEnumerable`2[System.Collections.Generic.KeyValuePair`2[System.Int32,System.String],System.String]' to type 'System.Collections.Generic.Dictionary`2[System.Int32,System.String]'.
at Test.Main()
As a bit of background, you can always cast from any interface type to a non-sealed class ("target"), even if that type doesn't implement the interface, because it's possible for another class derived from "target" to implement the interface.
From section 6.2.4 of the C# 5 specification:
The explicit reference conversions are:
...
From any class-type S to any interface-type T, provided S is not sealed and provided S does not implement T.
...
(The case where S does implement T is covered by implicit reference conversions.)
If you try to implicitly convert a value and there's no implicit conversion available, but there's an explicit conversion available, the compiler will give you the warning in your question. That means you can fix the compiler-error with a cast, but you need to be aware of the possibility of it failing at execution time.
Here's an example:
using System;
class Test
{
static void Main()
{
IFormattable x = GetObject();
}
static object GetObject()
{
return DateTime.Now.Second >= 30 ? new object() : 100;
}
}
Error message:
Test.cs(7,26): error CS0266: Cannot implicitly convert type 'object' to
'System.IFormattable'. An explicit conversion exists (are you missing a cast?)
So we can add a cast:
IFormattable x = (IFormattable) GetObject();
At this point, the code will work about half the time - the other half, it'll throw an exception.
How do you cast a COM interface pointer to void pointer and then back to the COM pointer? Here is some code to illustrate my problem. It's very similar to this sample code: _com_ptr_t assignment in VC++
CoInitialize(NULL);
COMLib::ICalcPtr pCalc = COMLib::ICalcPtr("MyLibrary.Calculator");
pCalc->doSomething();
CoUninitialize();
return 0;
Now, if I were to cast the pCalc object to void*, how would I cast it back to COMLib::ICalcPtr? For example, the second line in the following code gives me a compile error 'QueryInterface' : is not a member of 'System::Void'. Obviously, it's trying to call IUknown.QueryInterface() on the object. Preferably I would like to do this without creating a new interface (hence, without implicitly calling QueryInterface and AddRef).
void *test = pCalc;
COMLib::ICalcPtr pCalc2 = test;//'QueryInterface' : is not a member of 'System::Void'
FYI, the reason I'm doing this is that the object is going to be passed around from java to jni VC++ code as a void* type. I'm open to any suggestion on what to do or what is going on behind the scene.
Same way you pass any other opaque structure that either doesn't fit in a pointer or doesn't convert easily: by passing its address.
void* test = new COMLib::ICalcPtr(pCalc);
...
COMLib::ICalcPtr pCalc2 = *(COMLib::ICalcPtr*)test;
delete (COMLib::ICalcPtr*)test;
This will result in calls to AddRef and Release, but not QueryInterface.
I was wondering if there an established convention to specifying fixed point binary numbers in decimal format (with the use of a macro). I am not sure if this possible in C/C++, but perhaps this is implemented in some language(s) and there is a notational standard like 0x000000,1.2f,1.2d,1l,etc
Take this example for instance:
I am using Q15.16 for instance, but would like to have the convenience of specifying numbers in decimal format, perhaps something like this:
var num:Int32=1.2fp;
Presumably, the easiest way with regards to Haxe macros, numbers can be initialized with a function:
#:macro
fp_from_float(1.2);
But it would be nice to have a shorthand notation.
Have you seen Luca's Fixed Point example with Haxe 3 and Abstracts?
It's here:
https://groups.google.com/forum/?fromgroups=#!topic/haxelang/JsiWvl-c0v4
Summing it up, with the new Haxe 3 abstract types, you can define a type that will be compiled as an Int:
abstract Fixed16(Int)
{
inline function new(x:Int) this = x;
}
You can also define "conversion functions", which will allow you to automatically convert a float into Fixed16:
#:from public static inline function fromf(x:Float) {
#if debug
if (x >= 32768.0 || x < -32768.0) throw "Conversion to Fixed16 will overflow";
#end
return new Fixed16(Std.int(x*65536.0));
}
The secret here is the #:from metadata. With this code, you will already be able to declare fixed types like this:
var x:Fixed16 = 1.2;
Luca's already defined some operators, to make working with them easier, like:
#:op(A+B) public inline static function add(f:Fixed16, g:Fixed16) {
#if debug
var fr:Float = f.raw();
var gr:Float = g.raw();
if (fr+gr >= 2147483648.0 || fr+gr < -2147483648.0) throw "Addition of Fixed16 values will overflow";
#end
return new Fixed16(f.raw()+g.raw());
}
Again, the secret here is in #:op(A+B) metadata, which will annotate that this function may be called when handling addition. The complete GIST code is available at https://gist.github.com/deltaluca/5413225 , and you can learn more about abstracts at http://haxe.org/manual/abstracts
I know parts of this issue is covered by some posts here and I have looked at them and tested some but with no luck.
I have this native method signature which should populate the provided CBadgeData structure array with results:
int elc_GetBadges(int nHandle, char* cErr, int* nRecCount, CBadgeData** arr)
The CBadgeData structure is implemented as follows:
package test.elcprog;
import java.util.Arrays;
import java.util.List;
import com.sun.jna.Pointer;
import com.sun.jna.Structure;
public class CBadgeData extends Structure{
public static class ByReference extends CBadgeData implements Structure.ByReference { }
public int nBadgeID, nTrigger, nExtraData;
public String cName;
public CBadgeData(Pointer pointer){
super(pointer);
}
public CBadgeData(){ }
public String ToString() {
return nBadgeID + "," + nTrigger + "," + nExtraData + "," + cName;
}
#Override
protected List getFieldOrder() {
String[] s = new String[]{"nBadgeID","nTrigger","nExtraData","cName"};
return Arrays.asList(s);
}
}
My last try to craft this argument and call the method looked like this:
CBadgeData.ByReference[] badges = new CBadgeData.ByReference[max_items];
new CBadgeData.ByReference().toArray(badges);
int ret = inst.elc_GetBadges(handle, err, recCount, badges);
It fails with segmentation error.
My Question is what Java type should be provided here as an argument for the native CBadgeData** in the call to elc_GetBadges?
EDIT -1-
Populating the array myself (with or without terminating null pointer) didn't work and caused further Seg crashes. I then used Pointer[] arg as technomage suggested:
Pointer[] pointers = new Pointer[max_items];
for(int i=0; i<max_items; i++){
pointers[i] = new CBadgeData.ByReference().getPointer();
}
int ret = inst.elc_GetBadges(handle, err, recCount, pointers);
This caused no error but seems to not make any changes to the returning struct which should have contain 4 items in this case:
int bid = new CBadgeData(pointers[i]).nBadgeID; // this returns null for all items
Using explicit read() / write() on the struct led to Seg crashes again (on the read):
Any idea what am I still missing here?
EDIT -2-
Interestingly enough - using the Memory.get directly, after calling the native method, gets the correct results:
Memory m= (Memory)pointers[0];
System.out.println("1st int: "+m.getInt(0)); // this gets 24289 which is 5ee1
System.out.println("2nd int: "+m.getInt(4)); // this gets 3
System.out.println("3rd int: "+m.getInt(8)); // this gets 255
System.out.println("String: "+m.getString(12)); // this gets "Badge[5EE1]" as supposed
But the read() still crashes. Any thoughts?
I'm inferring that CBadgeData** input is intended to be an array of pointer to CBadgeData.
As such, the Structure.ByReference tagging is correct.
Structure.toArray() is probably not appropriate here, or at least not necessary (it allocates a contiguous block of structs in memory). You can just populate your array with CBadgeData.ByReference instances.
Perhaps your callee is expecting a NULL pointer at the end of the array? I don't see another indicator of the array length to the callee.
CBadgeData.ByReference[] badges = new CBadgeData.ByReference[max_items+1];
for (int i=0;i < badges.length-1;i++) {
badges[i] = new CBadgeData.ByReference();
}
badges[badges.length-1] = null;
Pretty sure that works. If for whatever reason there's a bug handling Structure.ByReference[], I know that Pointer[] is reliable and will do the same thing.
EDIT
If you use Pointer[] instead of Structure.ByReference[] (please post a bug to the project site if Structure.ByReference[] does not work), you will have to manually call Structure.write/read before/after your native function call, since JNA will not know that the pointers reference structures that need to be synched with native memory. I'd bet, however, that the cause of your crashes when using Structure.ByReference[] was simply that JNA was automatically calling Structure.read() after the call and triggered the same error that you see when calling it explicitly.
If you get a segfault on read, it likely means that your structure fields aren't properly aligned or defined, or (less likely) that you have corrupt data that can't be read properly. To diagnose this, set jna.dump_memory=true and print out your struct after calling Structure.write() to see if the contents of the structure appear as you'd expect. It'd also help to post the native and JNA forms of your structure here, if possible.