Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How to call a script function from C? #18

Closed
jarroddavis68 opened this issue Mar 19, 2021 · 2 comments
Closed

How to call a script function from C? #18

jarroddavis68 opened this issue Mar 19, 2021 · 2 comments

Comments

@jarroddavis68
Copy link

Possible?

I need my game library to call into specific routines in script.

Jarrod

@riicchhaarrd
Copy link
Owner

riicchhaarrd commented Mar 19, 2021

Edit

I misread your question, my mistake.
See https://github.com/riicchhaarrd/gsc/blob/master/src/standalone.c#L78

//example
se_addint(vm, 123);
se_addstring(vm, "test");
vm_exec_thread(vm, "your_script_routine", 2); //vm pointer, function name in script, number of arguments

//script function would look like this
your_script_routine(a, b)
{
//a would be test
//b would be 123
}

If you would like to do the opposite and expose C functions to the script, then read further below.

Writing glue code/wrapper

  1. Create your to be exported function
int my_function(vm_t *vm)
{
	int arg = se_getint(vm, 0); //get the first argument to my function from the stack
	
	//you can call your glue/wrapper c function here and return the value to gsc
	//e.g
	//se_addfloat(vm, sinf(se_getfloat(vm, 0));
	//return 1;
	
	if(arg == 1)
		se_addstring(vm, "my message"); //push a string onto the stack
	else if(arg == 2)
		se_addint(vm, 123); //we push integer 123 onto the stack
	else
		return 0; //return 0 means we don't have a return value and null will be pushed onto the stack
	return 1; //return 1 means we have a return value
}
  1. Add it to a array of type stockfunction_t
stockfunction_t my_function_set[] = {
	{"my_function", my_function},
	{NULL,NULL}
};
  1. After creating a vm instance (vm_t*) add it to the stock functions with se_register_stockfunction_set

Example of how to create a vm instance: (https://github.com/riicchhaarrd/gsc/blob/master/src/standalone.c#L73)

extern stockfunction_t my_function_set[];
se_register_stockfunction_set(vm, my_function_set);
  1. Run the VM and call your function
main()
{
	value = my_function(1);
	printf("value = " + value + "\n");
	value = my_function(2);
	printf("value = " + value + "\n");
	value = my_function(3);
	printf("value = " + value + "\n");
}

Alternative method using FFI

The exported function from the library has to be in cdecl calling convention and at the moment there's only support for x86.
Use #pragma comment(lib, "/path/to/library") with the path of the library

Example

Windows
#pragma comment(lib, "msvcrt.dll")

Linux
//replace the path with the path to your library that you want to import the C function from
#pragma comment(lib, "/lib/i386-linux-gnu/i686/cmov/libc.so.6")

#pragma comment(lib, "msvcrt.dll")

main()
{
	//When there's a conflict and printf is a builtin function of GSC and it exists in the library aswell, the GSC function will be used by default.
	//To combat this, if you put a dollar sign in front it will always call the exported function from the shared library.
	//e.g
	
	printf("Hello world\n"); //builtin function
	$printf("Hello world\n"); //FFI function
	
	//If the function isn't a builtin function, then omitting is fine too.
	i = atoi("12345");
	printf("i = %\n", i);

	p = malloc(1024);
	$snprintf(p,1024,"%d %s\n", i, "ok");
	$printf("%s", p);
	free(p);
}

@jarroddavis68
Copy link
Author

Ahh I see, wonderful thanks so much. Maybe make this info a wiki entry or something.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants