I just started using haxe(moving from AS3).
I'm trying to cast to Array, but it doesn't work, namely I get Cast type parameters must be Dynamic error when I try to compile. Below is the code I use:
var result: Array<String> = cast(["sometext"], Array<String>);
var arr: Array<Int> = new Array<Int>();
arr.push(1);
var vect : Array<Int> = cast(arr, Array<Int>);
var arr1: Array<Int> = [1, 2 ,3];
var vect1 : Array<Int> = cast(arr1, Array<Int>);
var arr2 = [1, 2 ,3];
var vect2 : Array<Int> = cast(arr2, Array<Int>);
Each of these 4 casts doesn't compile and gives the same error "Cast type parameters must be Dynamic". If I change the type parameter to Dynamic it won't work either. It fails with a different error.
Could someone explain why this way of casting is not working and how I can cast to Array?
Other casts:
var i: Int = 1;
var j: Int = cast(i, Int);
var str: String = "str";
var str1: String = cast(str, String);
var instance: CastToArrayTest = new CastToArrayTest();
var instance1: CastToArrayTest = cast(instance, CastToArrayTest);
Work just fine.
I think it's perhaps easier to explain with some sample code:
class Test {
static function main() {
var a = ["foo", "bar"];
$type(a); // Warning : Array<String>
// no need to cast or type simple assignments
var b = a;
$type(b); // Warning : Array<String>
// but lets define `x` as `Dynamic` (or something that we don't know what it is)
var x:Dynamic = ["foo", "bar"];
$type(x); // Warning: Dynamic
// we can simply assign it to an `Array<Dynamic>` variable (but we don't get any runtime checks!)
var c:Array<Dynamic> = x;
$type(c); // Warning: Array<Dynamic>
// we can also simply assign it to an `Array<String>` variable (but we don't runtime checks either!!)
var d:Array<String> = x;
$type(d); // Warning: Array<String>
// (if we want runtime checks, we need to code them with the `Type` apis)
// now, let's say we want to do
// var e:Array<String> = c;
// but that fails with `Type parameters are invariant`...
// we can instead use an unsafe cast
var e:Array<String> = cast c;
$type(e); // Warning: Array<String>
// type parameters are a compile time only feature
trace(showType(a), showType([1,2]));
trace(Std.is(a, Array), Std.is([1,2], Array));
// safe casts only check the current object (not its children), so we need to use them with `Dynamic` parameters
var f = cast(x, Array<Dynamic>);
$type(f); // Warning: Array<Dynamic>
// however, due to variance, we can't assign a the safe cast result of type `Array<Dynamic` to a `Array<String>` variable without an unsafe cast...
// which makes sense: our safe cast only checks that the object is an array, but the array doesn't know its own type nor has the safe cast checked the types of the children
}
static function showType(v:Dynamic)
{
switch Type.typeof(v) {
case TClass(cl):
return Type.getClassName(cl);
case other: // TODO handle other types
return Std.string(other);
}
}
}
You can play with this live at Try Haxe #CCaD5.
Putting in another way, here's how your "cast" examples would usually work and look like:
var result: Array<String> = cast ["sometext"];
var arr: Array<Int> = new Array<Int>();
arr.push(1);
var vect : Array<Int> = arr;
var arr1: Array<Int> = [1, 2 ,3];
var vect1 = arr1;
var arr2 = [1, 2 ,3];
var vect2 = arr2;
var i: Int = 1;
var j: Int = i;
var k = j;
var str: String = "str";
var str1: String = str;
var str2 = str1;
var instance: CastToArrayTest = new CastToArrayTest();
var instance1: CastToArrayTest = instance;
var instance2 = instance1;
You can see this live (with some additional info) at Try Haxe #97ADc.
Related
I'm trying to get an array of tensorflow box predictions from C++ to golang, but I'm not able to do it no matter what I do. I have a GO program that calls a function that does tensorflow detections in C++ using cgo. This all works and I'm able to get the predictions in C++. The problem is to transfer these predictions into GO as an array of 100 structs that each hold one prediction.
I'm able to set a pointer in GO and use this pointer address to set one struct in C++. The code for this is seen below.
I want to set an array of structs in C++ and retreive this array in GO. I thought it should be easy to just use the same pointer address as earlier and use this as the address for my C++ array. Then I could restore the struct from the pointer in GO. Does anyone have a solution for this?
GO
type PredictResult struct {
Loc [4]float32
Score int
Label int
}
var predictions PredictResult
predictions_ptr := unsafe.Pointer(&predictions)
C.LIB_predict(predictions_ptr)
fmt.Println("GO predictions; ", predictions)
bridge.hpp
struct PredictResult{
float Loc[4];
int64_t Score;
int64_t Label;
};
void LIB_predict(void* predictions);
bridge.cpp
void LIB_predict(void* predictions){
PredictResult *p = (PredictResult*)predictions;
p->Score = 6;
p->Label = 95;
}
Prints:
GO predictions; {[0 0 0 0] 6 95}
Assuming your C function returns the array as PredictResult* and assuming you know the length of the returned array (in the example below I assume 10, but you can replace it by whatever works), this approach should work:
// #include <stdio.h>
// #include <stdlib.h>
//
// typedef struct PredictResult {
// float Loc[4];
// int64_t Score;
// int64_t Label;
// } PredictResult;
//
// PredictResult* getOneResult() {
// PredictResult* p = (PredictResult*)calloc(1, sizeof(PredictResult));
// p->Score = 10;
// p->Label = 99;
// p->Loc[1] = 2.5;
// p->Loc[3] = 3.5;
// return p;
// }
//
// PredictResult* getTenResults() {
// PredictResult* parr = (PredictResult*)calloc(10, sizeof(PredictResult));
// parr[0].Score = 10;
// parr[0].Label = 99;
// parr[0].Loc[1] = 2.5;
// parr[0].Loc[3] = 3.5;
//
// parr[4].Score = 44;
// parr[4].Label = 123;
// parr[4].Loc[1] = 12.25;
// parr[4].Loc[3] = -40.5;
// return parr;
// }
//
//
import "C"
type PredictResult C.struct_PredictResult
func main() {
p := C.getOneResult()
if p == nil {
log.Fatal("got nil")
}
pp := (*PredictResult)(p)
fmt.Println(pp)
parr := C.getTenResults()
if parr == nil {
log.Fatal("got nil")
}
pslice := (*[1 << 28]PredictResult)(unsafe.Pointer(parr))[:10:10]
fmt.Println(pslice)
}
What you'll be most interested in is how the result of getTenResults is converted to a Go slice of the appropriate struct type. This is employing the technique recommended on the Go wiki.
Depending on the exact signature of your C function you may need to write a "bridge" function in the import "C" part to provide the data as convenient to Go, but this is the basic gist of it.
As an alternative, if you wish to allocate the slice on the Go side and pass in a pointer to C to populate, you can do this:
// void PopulateTenResults(void* arr) {
// PredictResult* parr = (PredictResult*)arr;
// parr[1].Score = 210;
// parr[1].Label = 299;
// parr[1].Loc[1] = 22.5;
// parr[1].Loc[3] = 23.5;
//
// parr[8].Score = 344;
// parr[8].Label = 3123;
// parr[8].Loc[1] = 312.25;
// parr[8].Loc[3] = -340.5;
// }
//
//
import "C"
And then in Go do:
prslice := make([]PredictResult, 10)
C.PopulateTenResults(unsafe.Pointer(&prslice[0]))
fmt.Println(prslice)
Of course the hard-coded 10 is just for simplicity here; you could pass the length of arr as a parameter to C.
You can pass a pointer to the first element in a slice and the length of the slice to C++ and treat it like a C-style array.
How can I type something like "print(list[1,4]);" in Dart?
For example:
int main() {
var products = new List(5);
products[0] = "Laptop";
products[1] = "Mouse";
products[2] = "Keyboard";
products[3] = "Monitor";
products[4] = "Microphone";
print(products[1]); // Mouse
print(products[1,3]); // I want to see 'Mouse,Monitor'
}
This is not directly supported in the SDK but you can easily make a extension on e.g. List to add this feature:
void main() {
final products = List<String>(5);
products[0] = "Laptop";
products[1] = "Mouse";
products[2] = "Keyboard";
products[3] = "Monitor";
products[4] = "Microphone";
print(products[1]); // Mouse
print(products.selectMultiple([1,3]).join(',')); // Mouse,Monitor
}
extension MultiSelectListExtension<E> on List<E> {
Iterable<E> selectMultiple(Iterable<int> indexes) sync* {
for (final index in indexes) {
yield this[index];
}
}
}
You can't make it so [1,3] (as in you own example) would be valid since the [] operator does only allow one argument. So instead, we need to make a method which takes our requested indexes as argument.
I do not know how to pass the value asynchronously to EM_ASM, here's how I try to do it (but JS says it's not a function):
const auto testFunc = [] (const char* data)
{
printf("data: %s\n", data);
}
EM_ASM_(
{
var funcResult = ($0);
var text = "data";
var lengthBytes = lengthBytesUTF8(text) + 1;
var stringOnWasmHeap = _malloc(lengthBytes);
stringToUTF8(text, stringOnWasmHeap, lengthBytes);
// exception thrown: TypeError: funcResult is not a function
funcResult(stringOnWasmHeap);
}, testFunc);
The documentation says that you can use a function (em_str_callback_func) of the em_str_callback_func type. But it doesn't say how to use it.
https://emscripten.org/docs/api_reference/emscripten.h.html
I don't know about passing callbacks, but if what you want to do is to return a value from JS, then the docs have such an example: you have to use EM_ASM_INT instead:
int x = EM_ASM_INT({
console.log('I received: ' + $0);
return $0 + 1;
}, 100);
printf("%d\n", x);
The API reference has another example for returning a string:
char *str = (char*)EM_ASM_INT({
var jsString = 'Hello with some exotic Unicode characters: Tässä on yksi lumiukko: ☃, ole hyvä.';
var lengthBytes = lengthBytesUTF8(jsString)+1;
// 'jsString.length' would return the length of the string as UTF-16
// units, but Emscripten C strings operate as UTF-8.
var stringOnWasmHeap = _malloc(lengthBytes);
stringToUTF8(jsString, stringOnWasmHeap, lengthBytes);
return stringOnWasmHeap;
});
printf("UTF8 string says: %s\n", str);
free(str); // Each call to _malloc() must be paired with free(), or heap memory will leak!
Once you have the value in C you can just call your testfunc directly.
I would like to get some help with c++.
Im trying to change the array name using value from variable. something like this:
global variables:
string array1[5][5];
string array2[5][5];
in a function:
string var;
if (option1) { var = "array1"; }
if (option2) { var = "array2"; }
var[1][1]="some data";
unfortunately this does not work. is there any way to manage the arrays like this?
Yes, you can use a pointer:
decltype(array1) *ptr{};
if ( option1 ) ptr = &array1;
else if ( option2 ) ptr = &array2;
if ( ptr )
(*ptr)[1][1] = "some data";
No, you can't. You should
string array1[5][5];
string array2[5][5];
string (*var)[5];
if (option1) { var = array1; }
if (option2) { var = array2; }
var[1][1]="some data";
No, there isn't.
You could use another level of array indexing:
string array[2][5][5];
int var;
if(option1) {var = 0;}
if(option2) {var = 1;}
array[var][1][1] = "some data";
i'd like to "define" 2 variables as 1 new variable, which then contains the contents/data of both previous variables.
Let's say the first variable is called 'var A' and the second 'var B',
can i combine those 2 in a new variable simply like this?
var ALL = var A + var B;
..or how is the correct syntax for this?
I hope this isn't too abstract? ;)
var A and B are both variables defining external geojson files, and I'd like to be able to "combine" these 2 in 1 new variable.
I would recommend using a function to handle combining them.
function combine(A,B) {
var C = {};
C.stuff_from_A = A.some_info;
C.stuff_from_B = B.some_info;
return C;
}
now you can perform what you ask.
var C = combine(A,B);
EDIT:
An example involving location data:
function combine(A,B) {
var C = {};
C.position_of_A = A.coordinate_info;
C.position_of_B = B.coordinate_info;
return C;
}
or to store the midpoint between them:
function combine(A,B) {
var C = {};
C.midpoint = average(A.location,B.location);
return C;
}
or more generally:
function combine() {
var C = {}; // Initialize
// Logic to combine and store info
return C; // Return the new object
}
EDIT 2
C.totalMarkers = [];
for (var i = 0; i < numberOfMarkersInA; i++) {
C.push(A.getMarker(i));
}
for (var i = 0; i < numberOfMarkersInB; i++) {
C.push(B.getMarker(i));
}
That is pseudo-code, those variable names will need to changed of course.
If there are the objects - serialize they and add with separator. If there is simple string, number, bool or something else, add with separator directly.
Sounds like you want to merge 2 geojson files into one. According to this answer, the concat method should do it for you:
var finalObj = json1.concat(json2); // Merge the 2 files together.