COMMUNITY

Hashlink: calling Haxe functions from C/C++

haxe-hl

(Alejandro Ramallo) #1

Hi there,
I’m trying to embed the hashlink vm into a C++ program so that I can load and work with .hl files. After copying the main.c file in the hashlink/src subfolder I was able to get it to load .hl files and run them through their main entrypoint. The relevant section for that is here (unmodified from hl repo):

	ctx.c.t = ctx.code->functions[ctx.m->functions_indexes[ctx.m->code->entrypoint]].type;
	ctx.c.fun = ctx.m->functions_ptrs[ctx.m->code->entrypoint];
	ctx.c.hasValue = 0;

But I was not able to find much helpful documentation on how to explore the types and functions in the loaded module.

I’ve been looking through the source for HL, but it’s not clear how to do some stuff. For example, how do I create a vclosure once I have an index

This is what I’ve got so far (the hl_lookup_* stuff was copied from obj_resolve_field function in obj.c):

        //iterate through all hl_type(s)
	for(int i=0; i<ctx.code->ntypes; i++){
		hl_type *type = ctx.code->types+i;		

		if(type->kind != HOBJ)
			continue;

                //found the specific class I want by name:
		if(ucmp(type->obj->name, USTR("MyHaxeClass") == 0){
			hl_runtime_obj *rt = hl_get_obj_rt(type);
			hl_field_lookup *f_myfunc = NULL;
			int hfield = hl_hash_gen(USTR("my_haxe_function"), false);
			do {
				hl_field_lookup *f = hl_lookup_find(rt->lookup,rt->nlookup,hfield);
				if( f ){
					f_myfunc = f;
					break;
				};
				rt = rt->parent;
			} while( rt );

			if(f_myfunc == NULL){
				printf("Didn't find function\n");
				break;
			}

			int fidx = -f_myfunc->field_index-1; //index to methods array I'm assuming?			
			vclosure *cl = (vclosure*) rt->methods[fidx]; //yeah right
			hl_dyn_call_safe(cl,NULL,0,NULL); //crash probably
		}

	}

The above doesn’t work because it doesn’t even find the function I’m looking for. I’m also pretty sure a basic cast to a vclosure isn’t enough.

My end goal is this:

  • write Haxe code with many different classes and compile to HL bytecode
  • load bytecode in my C++ program
  • be able to create instances of classes in the loaded module and call their members

Basically, I’m trying to use the loaded HL module as kind of a shared library in my C++ program. I need to be able to instantiate classes, read their variables, call their functions, and read their return values. I don’t really care about the performance or portability (although that’s always nice!)

So can anyone help me out with this? I’d greatly appreciate it!


(Nicolas Cannasse) #2

In order to create an instance, you need to call hl_alloc_obj(type) and then call the constructor which is not easy to fetch using the current api because it’s inside the corresponding Class.__constructor__ field (the class being the “global” value in type->obj->rt->global_value)

For closures, you can call hl_alloc_closure_void(type,funptr) to create a HL function-value with just the function type and the JIT (or C) function pointer, or hl_alloc_closure_ptr(type,funptr,value) to have the first argument be set to the given value.

Hope that helps.