Arrays of strings in Managed C++ - c++

I'm trying to write an application in Managed C++, but I cannot work out how to declare an array of strings.
String^ linet[];
throws an error
'System::String ^' : a native array cannot contain this managed type
So I suppose there's a different way to do this for managed data types. What exactly is it?

Do you really mean Managed C++? Not C++/CLI?
Assuming you're actually using C++/CLI (because of the error message you posted), there are two ways to do this:
array<String^>^ managedArray = gcnew array<String^>(10);
will create a managed array, i.e. the same type as string[] in C#.
gcroot<String^>[] unmanagedArray;
will create an unmanaged C++ array (I've never actually tried this with arrays - it works well with stl containers, so it should work here, too).

http://www.codeproject.com/KB/mcpp/cppcliarrays.aspx
That should have all the answers you need :)
When working with Managed C++ (aka. C++/CLI aka. C++/CLR) you need to consider your variable types in everything you do. Any "managed" type (basically, everything that derives from System::Object) can only be used in a managed context. A standard C++ array basically creates a fixed-size memory-block on the heap, with sizeof(type) x NumberOfItems bytes, and then iterates through this. A managed type can not be guarenteed to stay the same place on the heap as it originally was, which is why you can't do that :)

You use a collection class from .Net. For example:
List<String^>^ dinosaurs = gcnew List<String^>();

Related

How to create Apache Arrow vectors in Java, pass them to C++ code through JNI, read/write them in C++

I've been reading the Apache Arrow docs, and I've figured out how to use it in Java and C++. But what I'd like to do is offload some work to JNI (C/C++) code from Java, and the documentation (e.g. https://arrow.apache.org/docs/java/cdata.html) just doesn't seem to cover my use cases, and methods in the example (e.g. getMemoryAddress on IntVector) just don't seem to exist like they do in the examples. I want to start simple, so here's what I'd like to do:
Allocate two Arrow IntVector's in Java and fill them with data
Allocate space for another IntVector in Java for the result
Get whatever native pointers I need from those vectors and pass them through a JNI call
Wrap those vectors in C++ so I can access them.
Do whatever work I want to offload and finalize the result vector
Return to Java and have the result accessible.
Can anyone point me to an example or some tips on how to do this?
BTW, the examples also use JavaCPP instead of JNI. But I already have a bunch of JNI code in this project, and I'd rather not mix in another kind of bridge if it's not necessary.
Thanks.
I tried allocating IntVector objects in Java, but I can't tell which naive pointers I have to retrieve to pass to C++ to provide proper access to those vectors.
JavaCPP is merely a convenience for the example, JNI is fine.
The C Data Interface is still what you want. When you say "get whatever native pointers I need": that is exactly what a struct ArrowArray is in the C Data Interface. Use the C Data Interface module in Java to export your Java arrays and get the address of a struct ArrowArray, and then pass that address to your C++ code via JNI. Then, use libarrow's C Data Interface implementation to import the arrays and work with them.
When the C++ side is done, it does the same thing: it exports the result vector and returns an address to Java via JNI; the Java code then imports the vector from that address.

Is it possible to put different datatypes in the same List<>

Is it possible to put different datatypes in the same List<> in C#?
myList.Add("Joe");
myList.Add(25);
Assuming you are using Java, yes. Everything is an Object in Java and Arrays take Objects. Good luck getting them back out though.

C , How can I pass a multidimensional array to a function in a CLR/Class Library project

I'm trying to write a dll in c++ (under CLR/Class Library) to be added as a reference in a vb.net project.
I explain the issue I have:
when I write a generic function without using array or pointers I can visualize and use this function once I have build my c++ project and added as a reference the resulting dll to my vb.net project. But, when I try to write a function in which I have to use a multidimensional array, in the methods shown in the 'objects viewer' in vb my new function does not exists.
Is there something I should know in particular to use multidimensional array as a parameter in functions, to be visible when I add as a reference my dll?
Or maybe there is complete different way I have to follow?
Please, let me know how can I resolve this problem.
Thanks for any help you could give me!!
One solution, using a C++/CLI DLL as a mediator. C++/CLI can deal with both native and managed types. So you can first passed the natvie multidimensional array as a parameter to C++/CLI, then in the C++/CLI Dll, you can creat a managed multidimensional array, and assign the values of the native one to the managed one. Finally, this managed one can be passed to VB.NET.
I used to use this solution to pass the multidimensional array from C to C#, I tried to find a better solution at that time, but I didn't. I hope there will be now.

Trouble with adding C++ objects to Objective C collections (NSSet)

I'm busy implementing ZXing with a QRCodeReader into my project.
QRCodeReader is mainly C++ and my project objective-C.
I have managed to implement it properly so I can use the QRCodeReader objects into my objective-C implementation (.mm file).
But now I need to pass this C++ object to the zxWidController.reader property.
This means I will have to set the C++ object into an NSSet Object.
QRCodeReader* qrcodeReader = new QRCodeReader();
NSSet *readers = [[NSSet alloc ] init];
[readers setByAddingObject:(id)qrcodeReader];
widController.readers = readers;
[readers release];
The code above does the trick. I casted the C++ object to (id) and now it compiles properly. But is this the proper way to do it?
Is this manner of programming the proper way to do this?
Are there any other / better ways to achieve my goal?
A C++ type is not an Objective C type. You cannot send it messages, in particular retain and release, which NSSet does. There's an Objective C type of the same name that you want to use. (I'll update my other answer).
The code above does the trick. I casted the C++ object to (id) and now
it compiles properly. But is this the proper way to do it?
No. You can't just make an arbitrary pointer into a valid Objective-C object pointer by casting it to id.
Is this manner of programming the proper way to do this?
Again, no.
Are there any other / better ways to achieve my goal?
You can try any of the following:
Redefine your zxWidController class to take a pointer to a C++ object instead of an Obj-C object.
Wrap qrcodeReader in a NSValue.
Take a look at NSPointerArray as a replacement for NSSet. Definitely read the docs before you try to use it -- you have to configure it's memory management policies to do the right thing for the type of pointer you're storing.
Minor nitpick: Forgetting for a moment about the fact that qrcodeReader points to a C++ object, it seems silly to create an empty set just so that you can add an object to it. If you were going to use an Obj-C set, then either create it using +setWithObject: or use NSMutableSet instead.

How to generate C++ Dynamic Objects names?

I'd like to generate a number of objects (in C++) based on the amount/number the user enters.
Now I've somewhere heard that it has to be done using pointer tricks, creating a pointer to an array of the Object type required, and then dynamically increasing the size of array ( at runtime ).
Isn't there a workaround of directly using names like
Object1, Object2..... ObjectX
instead of having
Classname *Object[]
and then using the array index to get the object ?
In either case, it'd be great if someone could clarify on the issue.
Thanks !
If you want dynamically-sized array, then use std::vector. You won't be able to resize a built-in array.
If you want to be able to get an object by string name, then you should use std::map, it has an indexer:
std::map<string, Classname> myMap;
myMap["Object1"] = Classname();
Classname newClassname = myMap["Object1"];
So far no-one has explained why your thinking is flawed. C++ is a compiled language, and it goes to great lengths to turn the source program into efficient machine code. For this reason, the names you give variables are available to the program only at compile time, when you turn it from source into an executable file. Afterwards, when you want to create objects dynamically, those kinds of information are no longer available. The program only knows about the machine addresses where operands to machine instructions are located.
No, there isn't. Moreover, you don't need to; use std::vector.
When I began programming 9 years ago I asked myself the same question. The answer is: you can't.
You can indeed use an array and resize it dynamically, however using an stl vector is much easier (once you learn how to use it).
You can not do that because C++ doesn't have an "environment" (reflection) where variables (and metadata) can reside. Moreover, in C++ all variable names are vanished when the code is compiled.
A way to achieve the effect you want is to use a Map where the keys are strings.