如何从VM调用本机函数?

 2023-01-21    340  

问题描述

由本机i的意思是写在C ++或C

如何从VM调用本机函数?

我正在制作基于Java的编程语言,因为它具有vm和一种字节编译器的语言.

实现语言的功能,例如for循环,变量,算术等,对我来说不是问题.但是,执行像Java一样的本机函数是.

我需要本机函数,以使以我的语言编写的程序创建Windows,与硬件和操作系统交互,并做任何不简单数学的事情.

我听说过但是,我不确定如何实施这样的事情.

由于我的VM在C ++中实现,我知道我可以在Compile-time时拥有我本机函数的#include hpp文件,然后它可以动态加载dll’s或so’s,但是,这似乎并不是一个很好的解决方案,因为您每次希望它能够执行另一个本机函数时都必须重新编译VM.

问题归结为:C ++程序(VM)如何动态(在运行时,按字节指示,更精确地)具有C ++函数的加载库,然后执行这些函数而无需这些函数,而无需它们.在某些标题文件中?

推荐答案

查看 libffi .它提供了调用给定函数地址和调用签名的任何功能的方法.

您如何找出该签名应取决于您的上下文.您可以根据参数类型推断出广泛的调用. jna 从显式Java接口,方法声明或动态呼叫参数中输入本机呼叫签名.

超越简单函数调用来处理构造函数,内存管理和对象方法调度更为复杂,但仍然基于相同的基本原理.

其他推荐答案

我尚未讨论过的一个主题是如何通过新语言vm函数调用C ++堆栈的参数,以及如何将返回值从C ++函数传递回VM.

可以说,您想在新语言中使POW(3)功能可用.
提醒您,POW()签名为

double pow ( double base, double power )

最简单的方法就是这样

void
language::pow( VM * pVM )
{
    double arg2 = pVM->PopDouble();
    double arg1 = pVM->PopDouble();
    double result = pow( arg1, arg2 );
    pVM->PushDouble( result );
}

,但这听起来不像您所追求的.合并dlopen()&dlsym()会得到您的东西

void
language::pow( VM * pVM )
{
    double arg2 = pVM->PopDouble();
    double arg1 = pVM->PopDouble();
    void *handle = dlopen("libm", RTLD_LAZY);
    if (!handle) { /*...return; ...*/ }
    typedef double (* pfPow ) ( double, double );
    pfPow pPow = (pfPow) dlsym(handle, "pow");
    if (!pPow) { /*...return; ...*/ }
    double result = (* pPow )( arg1, arg2 );
    pVM->PushDouble( result );
}

但这甚至更糟.您仍然需要每个C ++功能的存根功能,您希望您的语言能够访问.

听起来您希望您的语言具有

之类的东西

double result = eval_double( "libm", "pow", arg1, arg2 );

我不知道如何在C ++中实现. Varags支持获取任何类型的C ++参数.但是没有用于推动任意类型的C ++参数的API.

以上所述是小编给大家介绍的如何从VM调用本机函数?,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对77isp云服务器技术网的支持!

原文链接:https://77isp.com/post/26296.html

=========================================

https://77isp.com/ 为 “云服务器技术网” 唯一官方服务平台,请勿相信其他任何渠道。