How do I write to use Dictionary<T,U>.Enumerator with #:native extern - haxe

It seems
#:native('System.Collections.Generic.Dictionary')
extern class Dictionary<T, U>
is valid, but it does not seems to apply to nested class of generic class.
I want to write in Haxe, with my own 'extern class' bridge, something like:
struct K {
string x;
}
struct V {
string y;
}
class Foo {
public void foo(Dictionary<K, V> d) {
Dictionary<K,V>.Enumerator e = d.GetEnumerator();
while (e.MoveNext()) {
Debug.Log(e.Current.Key.x);
Debug.Log(e.Current.Value.y);
}
}
}

Related

Specializing formatting for pointer to class

I need to provide format-magic to a class hierarchy and usually those things are passed around via pointer. This example here works currently on master:
#include <type_traits>
#include <sstream>
#include <fmt/format.h>
#include <fmt/ostream.h>
struct A {
virtual ~A() {}
virtual std::string name() const { return "A"; }
};
struct B : A {
virtual std::string name() const { return "B"; }
};
template <typename T>
struct fmt::formatter<T, std::enable_if_t<std::is_base_of<A, std::remove_const_t<std::remove_pointer_t<T>>>::value, char>> : fmt::formatter<std::string> {
template <typename FormatCtx>
auto format(const A* a, FormatCtx& ctx) {
return fmt::formatter<std::string>::format(a->name(), ctx);
}
};
template<class... T>
[[noreturn]] void err(fmt::format_string<T...> s, T&&... args) {
throw std::logic_error(fmt::format(s, std::forward<T>(args)...));
}
int main() {
A* a = new A();
B* b = new B();
const A* x = new A();
const B* y = new B();
fmt::print("{}, {}, {}, {}\n", a, b, x, y);
std::ostringstream oss;
fmt::print(oss, "{}\n", a);
err("{}, {}, {}, {}\n", a, b, x, y);
}
However, when I'm going to the latest release 8.1.1, I'm getting:
error: static assertion failed: Formatting of non-void pointers is disallowed.
Now my question is: What's the plan here? Can I do this in future versions of fmt or is this more of an accident?
This is definitely a regression. Supporting a hierarchy of classes can be done as documented in https://fmt.dev/latest/api.html#formatting-user-defined-types using references instead of pointers:
#include <type_traits>
#include <fmt/format.h>
struct A {
virtual ~A() {}
virtual std::string name() const { return "A"; }
};
struct B : A {
virtual std::string name() const { return "B"; }
};
template <typename T>
struct fmt::formatter<T, std::enable_if_t<std::is_base_of<A, T>::value, char>> :
fmt::formatter<std::string> {
template <typename FormatCtx>
auto format(const A& a, FormatCtx& ctx) {
return fmt::formatter<std::string>::format(a.name(), ctx);
}
};
int main() {
B b;
A& a = b;
fmt::print("{}", a); // prints "B"
}

How to apply a function to the active enum member like C++'s std::visit?

I have a serialization library in C++ which serializes types into buffers for transmitting over network and to disk and I want to port it to Rust. The library supports serializing std::variant types that contain serializable types using the index and std::visit which can be used with a template lambda to serialize the active member in the variant:
template<Serializable ... Object>
void serialize_variant(const std::variant<Object...>& var) {
serialize_number(var.index());
std::visit([](const auto& item) { serialize_object(item); }, var);
}
Rust has match which is useful when I know the enum's type but I can't match on an arbitrary enum. I also can't get the index of the member of an enum to serialize it before the item.
I have something like this incorrect code:
trait Serilizable {
fn write_to_buffer(&self, buff: &[u8]) {}
}
impl Serilizable for i32 {
/* implement serilization */
}
impl Serilizable for f64 {
/* implement serilization */
}
impl Serilizable for String {
/* implement serilization */
}
enum ToSerialize {
I32(i32),
F64(f64),
Str(String),
}
fn serialize_object(obj: &Serilizable, buff: &[u8]) {
obj.write_to_buffer(buff);
}
fn serialize_manually(var: &ToSerialize, buff: &[u8]) {
match ToSerialize {
I32(i) => {
serialize_object(&0, buff);
serialize_object(i, buff);
}
F64(f) => {
serialize_object(&1, buff);
serialize_object(i, buff);
}
Str(s) => {
serialize_object(&2, buff);
serialize_object(s, buff);
}
}
}
I want to replace serialize_manually with a generic function that accepts any enum of Serializable types and does something similar.

How to use read-only borrowed Rust data by multiple Java threads?

I have a struct Foo and FooRef which has references to data from Foo:
struct Foo { /* ... */ }
struct FooRef<'foo> { /* ... */ }
impl Foo {
pub fn create_ref<'a>(&'a self) -> FooRef<'a> { /* ... */ }
}
Now Foo directly cannot be used in the logic; I need FooRef. Creating FooRef requires lots of computation, so I do it once just after creating the Foo instance. FooRef is immutable; it's only used for reading data.
Multiple threads needs to access this FooRef instance. How can I implement this? The calling threads are Java threads and this will be used with JNI. This prevents using a scoped threadpool, for example.
Another complication is that when I have to refresh the Foo instance to load new data into it. I then also need to recreate the FooRef instance as well.
How can this be achieved thread-safely and memory-safely? I tried messing around with pointers and RwLock but that resulted in a memory leak (the memory usage kept on adding on each reload). I am a Java developer that is a newbie to pointers.
The data in Foo is mostly text and about 250Mb. The FooRef is mostly strs and structs of strs borrowed from Foo.
My Java usage explanation
I use two long variables in a Java class to store pointers to Foo and FooRef. I use a static ReentrantReadWriteLock to guard these pointers.
If the data need to be updated in Foo, I acquire a write lock, drop FooRef, update Foo, create a new FooRef and update the ref pointer in Java.
If I need to read the data (i.e. when I am not updating Foo), I acquire a read lock and use the FooRef.
The memory leak is visible only when multiple Java threads are calling this code.
Rust:
use jni::objects::{JClass, JString};
use jni::sys::{jlong, jstring};
use jni::JNIEnv;
use std::collections::HashMap;
macro_rules! foo_mut_ptr {
($env: expr, $class: expr) => {
$env.get_field(*$class, "ptr", "J")
.ok()
.and_then(|j| j.j().ok())
.and_then(|ptr| {
if ptr == 0 {
None
} else {
Some(ptr as *mut Foo)
}
})
};
}
macro_rules! foo_ref_mut_ptr {
($env: expr, $class: expr) => {
$env.get_field(*$class, "ptrRef", "J")
.ok()
.and_then(|j| j.j().ok())
.and_then(|ptr| {
if ptr == 0 {
None
} else {
Some(ptr as *mut FooRef)
}
})
};
}
macro_rules! foo_mut {
($env: expr, $class: expr) => {
foo_mut_ptr!($env, $class).map(|ptr| &mut *ptr)
};
}
macro_rules! foo_ref {
($env: expr, $class: expr) => {
foo_ref_mut_ptr!($env, $class).map(|ptr| &*ptr)
};
}
#[allow(non_snake_case)]
#[no_mangle]
pub unsafe extern "system" fn Java_test_App_create(_env: JNIEnv, _class: JClass) -> jlong {
Box::into_raw(Box::new(Foo::default())) as jlong
}
#[allow(non_snake_case)]
#[no_mangle]
pub unsafe extern "system" fn Java_test_App_createRef(env: JNIEnv, class: JClass) -> jlong {
let foo = foo_mut!(env, class).expect("createRef was called on uninitialized Data");
let foo_ref = foo.create_ref();
Box::into_raw(Box::new(foo_ref)) as jlong
}
#[allow(non_snake_case)]
#[no_mangle]
pub unsafe extern "system" fn Java_test_App_reload(env: JNIEnv, class: JClass) {
let foo = foo_mut!(env, class).expect("foo must be initialized");
*foo = Foo {
data: vec!["hello".to_owned(); 1024 * 1024],
};
}
#[allow(non_snake_case)]
#[no_mangle]
pub unsafe extern "system" fn Java_test_App_destroy(env: JNIEnv, class: JClass) {
drop_ptr(foo_ref_mut_ptr!(env, class));
drop_ptr(foo_mut_ptr!(env, class));
}
#[allow(non_snake_case)]
#[no_mangle]
pub unsafe extern "system" fn Java_test_App_destroyRef(env: JNIEnv, class: JClass) {
drop_ptr(foo_ref_mut_ptr!(env, class));
}
unsafe fn drop_ptr<T>(ptr: Option<*mut T>) {
if let Some(ptr) = ptr {
let _foo = Box::from_raw(ptr);
// foo drops here
}
}
#[derive(Default)]
struct Foo {
data: Vec<String>,
}
#[derive(Default)]
struct FooRef<'a> {
data: HashMap<&'a str, Vec<&'a str>>,
}
impl Foo {
fn create_ref(&self) -> FooRef {
let mut data = HashMap::new();
for s in &self.data {
let s = &s[..];
data.insert(s, vec![s]);
}
FooRef { data }
}
}
Java:
package test;
import java.util.concurrent.locks.ReentrantReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock.ReadLock;
import java.util.concurrent.locks.ReentrantReadWriteLock.WriteLock;
public class App implements AutoCloseable {
private final ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
private final ReadLock readLock = lock.readLock();
private final WriteLock writeLock = lock.writeLock();
private volatile long ptr;
private volatile long ptrRef;
private volatile boolean reload;
static {
System.loadLibrary("foo");
}
public static void main(String[] args) throws InterruptedException {
try (App app = new App()) {
for (int i = 0; i < 20; i++) {
new Thread(() -> {
while (true) {
app.tryReload();
}
}).start();
}
while (true) {
app.setReload();
}
}
}
public App() {
this.ptr = this.create();
}
public void setReload() {
writeLock.lock();
try {
reload = true;
} finally {
writeLock.unlock();
}
}
public void tryReload() {
readLock.lock();
debug("Got read lock");
if (reload) {
debug("Cache is expired");
readLock.unlock();
debug("Released read lock coz expired");
writeLock.lock();
debug("Got write lock");
try {
if (reload) {
fullReload();
}
readLock.lock();
debug("Got read lock inside write");
} finally {
writeLock.unlock();
debug("Released write lock");
}
}
readLock.unlock();
debug("Released read lock");
}
private void fullReload() {
destroyRef();
debug("Dropped ref");
debug("Reloading");
reload();
debug("Reloading completed");
updateRef();
debug("Created ref");
reload = false;
}
private void updateRef() {
this.ptrRef = this.createRef();
}
private native void reload();
private native long create();
private native long createRef();
private native void destroy();
private native void destroyRef();
#Override
public void close() {
writeLock.lock();
try {
this.destroy();
this.ptrRef = 0;
this.ptr = 0;
} finally {
writeLock.unlock();
}
}
private static void debug(String s) {
System.out.printf("%10s : %s%n", Thread.currentThread().getName(), s);
}
}
The problem that I was thinking as memory leak wasn't actually a memory leak. The issue was that the allocator was using thread local arenas. So, whatever thread was reloading 250MB of data was leaving the allocated space as is and not returning it to the system. This issue was not specific to JNI, but also happening in pure safe rust code. See Why multiple threads using too much memory when holding Mutex
The default number of arenas created defaults to 8 * cpu count = 64 in my case. This setting can be overridden by setting MALLOC_ARENA_MAX env variable.
So I resolved this issue by setting MALLOC_ARENA_MAX env variable to 1 . So, the approach I took is fine. It was just platform specific issue.
This issue was occurring only in Ubuntu in WSL. I also tried the same code without any tweaking on Windows 10 and it works perfectly without any issues.

Returning a pointer to an object from a Rust library for later reuse?

I want to call a Rust library which will create an object increment_engine for me and return a pointer to it (or anything persistent). This engine would be given a parameter on creation.
Later I could call this object's increment(a) method and it would add the remembered parameter to a and return the result. Here is the code:
import com.sun.jna.Library;
import com.sun.jna.Native;
import com.sun.jna.Platform;
public class App {
public interface MyLibrary extends Library {
MyLibrary INSTANCE = (MyLibrary) Native.loadLibrary("myjavarust", MyLibrary.class);
double addition(double a , double b);
int set_increment_engine(double parameter);
double use_increment_engine(int engine_id, double a);
}
public static void main() {
int sum = MyLibrary.INSTANCE.addition(13.0,5.0);
System.out.println(sum); // this works and prints 18 (=13+5)
engine_id = MyLibrary.INSTANCE.get_increment_engine(13.0);
double result = MyLibrary.INSTANCE.use_increment_engine(engine_id,5.0);
System.out.println(result); // this should also return 18
}
}
The last three lines of main() show how I would like to use the "increment engine"
The Rust pseudo-code should look like this.
extern crate libc;
use libc::{c_double, uint32_t};
#[no_mangle]
pub extern "C" fn addition(a: f64, b: f64) -> f64 {
a + b
}
#[no_mangle]
pub extern "C" fn set_increment_engine(param: c_double) -> uint32_t {
let engine = IncrementEngine { param: param };
return_engine_id_somehow
}
#[no_mangle]
pub extern "C" fn use_increment_engine(engine_id: uint32_t, a: c_double) -> c_double {
let engine = find_engine_somehow(engine_id);
engine.increment(a)
}
struct IncrementEngine {
param: c_double,
}
impl IncrementEngine {
pub fn increment(&self, a: f64) -> f64 {
a + self.param
}
}
I have successfully tested the function "addition" which does not require the persistent "increment machine", but I would like to use the engine pattern (obviously for more complex things than incrementing a double). I have investigated many sites about passing data across library boundaries and there is lots of information on passing structures etc, but not so many on "persistent pointers". The only thing close to the solution is in the Nomicon where the Rust library calls the caller back which allows for the object to persist, but it is really not applicable to my use-case.
engine_id in the example is an int, but presumably it would be some kind of pointer to the object created by set_increment_engine.
This approach can be taken:
import com.sun.jna.Library;
import com.sun.jna.Native;
import com.sun.jna.Platform;
public class App {
public interface MyLibrary extends Library {
MyLibrary INSTANCE = (MyLibrary) Native.loadLibrary("myjavarust", MyLibrary.class);
long set_increment_engine(double parameter);
double use_increment_engine(long engine, double a);
void free_increment_engine(long engine);
}
public static void main(String[] args) {
long engine = MyLibrary.INSTANCE.set_increment_engine(13.0);
double result = MyLibrary.INSTANCE.use_increment_engine(engine, 5.0);
System.out.println(result); // returns correctly 18.0
MyLibrary.INSTANCE.free_increment_engine(engine);
}
}
with this lib.rs code:
extern crate libc;
use libc::c_double;
#[no_mangle]
pub extern "C" fn set_increment_engine(param: c_double) -> *mut IncrementEngine {
let engine = IncrementEngine { param: param };
Box::into_raw(Box::new(engine))
}
#[no_mangle]
pub extern "C" fn use_increment_engine(engine_ptr: *mut IncrementEngine, a: c_double) -> c_double {
let engine = unsafe {
assert!(!engine_ptr.is_null());
&mut *engine_ptr
};
engine.increment(a)
}
#[no_mangle]
pub extern "C" fn free_increment_engine(engine_ptr: *mut IncrementEngine) {
if engine_ptr.is_null() {
return;
}
unsafe {
Box::from_raw(engine_ptr);
}
}
pub struct IncrementEngine {
param: c_double,
}
impl IncrementEngine {
pub fn increment(&self, a: f64) -> f64 {
a + self.param
}
}
Note that the function addition was removed as it only served for purpose of the question.

How to compile this VC++ program?

Im very new to VC++. Yesterday my VC++ instructor gave us this code and asked us to make it as a exe. I have no idea of where to start and end. How to make this single file into exe. How and where to paste this working code in visual studio. If my question sounds too dumb, sorry. But i'm. Please help me out in making an exe from this single file. By the way this is Josephus circle algorithm
Code :
//////////////////Header file
#include<iostream.h>
template <class T>
class ex
{
private:
struct node
{
T data;
struct node *next;
};
struct node *head,*front,*rear;
public:
ex()
{
head=new node;
head->next=NULL;
front=rear=head;
}
void enqueue(T x);
T dequeue();
void print();
void move_next();
};
//////////////////Implementation file
#include "ex.h"
template <class T>
void ex<T>::enqueue(T x)
{
node *p;
p=new node;
p->data=x;
if(head->next==NULL)
{
front=rear=p;
head->next=p;
p->next=p;
}
else
{
rear->next=p;
p->next=front;
rear=rear->next;
}
}
template<class T>
T ex<T>::dequeue()
{
node *t;
T x;
t=front;
x=t->data;
front=front->next;
rear->next=front;
delete(t);
return x;
}
template<class T>
void ex<T>::print()
{
node *p=front;
do
{
cout<<p->data<<endl;
p=p->next;
}while(p!=rear->next);
}
template<class T>
void ex<T>::move_next()
{
front=front->next;
rear=rear->next;
}
/////////////////Application file
#include "ex.cpp"
void main()
{
ex<int> e;
int m,n,i,d;
cout<<"Enter the number of people";
cin>>n;
cout<<"Enter the number of passes";
cin>>m;
for(i=1;i<=n;i++)
e.enqueue(i);
cout<<"The players are
";
e.print();
cout<<"Eliminated in order
";
while(n>1)
{
for(i=1;i<=m;i++)
e.move_next();
d=e.dequeue();
cout<<d<<endl;
n--;
}
d=e.dequeue();
cout<<"Winning player: "<<d<<endl;
}
Make the first file named ex.h
#include<iostream.h>
template <class T>
class ex
{
private:
struct node
{
T data;
struct node *next;
};
struct node *head,*front,*rear;
public:
ex()
{
head=new node;
head->next=NULL;
front=rear=head;
}
void enqueue(T x);
T dequeue();
void print();
void move_next();
};
Second file into ex.cpp
#include "ex.h"
template <class T>
void ex<T>::enqueue(T x)
{
node *p;
p=new node;
p->data=x;
if(head->next==NULL)
{
front=rear=p;
head->next=p;
p->next=p;
}
else
{
rear->next=p;
p->next=front;
rear=rear->next;
}
}
template<class T>
T ex<T>::dequeue()
{
node *t;
T x;
t=front;
x=t->data;
front=front->next;
rear->next=front;
delete(t);
return x;
}
template<class T>
void ex<T>::print()
{
node *p=front;
do
{
cout<<p->data<<endl;
p=p->next;
}while(p!=rear->next);
}
template<class T>
void ex<T>::move_next()
{
front=front->next;
rear=rear->next;
}
And the third file into Main.cpp or something.
#include "ex.cpp"
void main()
{
ex<int> e;
int m,n,i,d;
cout<<"Enter the number of people";
cin>>n;
cout<<"Enter the number of passes";
cin>>m;
for(i=1;i<=n;i++)
e.enqueue(i);
cout<<"The players are
";
e.print();
cout<<"Eliminated in order
";
while(n>1)
{
for(i=1;i<=m;i++)
e.move_next();
d=e.dequeue();
cout<<d<<endl;
n--;
}
d=e.dequeue();
cout<<"Winning player: "<<d<<endl;
}
Then compile it. Also, it's supposed to be int main() not void main()
To add to Alex F. answer, you will also need to create an ex.h file and an ex.cpp file and paste their respective code inside

Resources