Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/384.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 如何从VM调用本机函数? 或所以这似乎不是一个好的解决方案,因为每次您希望VM能够执行另一个本机函数时,都必须重新编译VM 问题是这样的:一个C++程序(VM)如何动态地(在运行时,由字节码指示,以更精确地)用C++函数加载库,然后执行这些函数而不在某些头文件中预先声明?查看。它提供了调用给定函数地址和调用签名的任何函数的方法_Java_C++_Java Native Interface_Shared Libraries - Fatal编程技术网

Java 如何从VM调用本机函数? 或所以这似乎不是一个好的解决方案,因为每次您希望VM能够执行另一个本机函数时,都必须重新编译VM 问题是这样的:一个C++程序(VM)如何动态地(在运行时,由字节码指示,以更精确地)用C++函数加载库,然后执行这些函数而不在某些头文件中预先声明?查看。它提供了调用给定函数地址和调用签名的任何函数的方法

Java 如何从VM调用本机函数? 或所以这似乎不是一个好的解决方案,因为每次您希望VM能够执行另一个本机函数时,都必须重新编译VM 问题是这样的:一个C++程序(VM)如何动态地(在运行时,由字节码指示,以更精确地)用C++函数加载库,然后执行这些函数而不在某些头文件中预先声明?查看。它提供了调用给定函数地址和调用签名的任何函数的方法,java,c++,java-native-interface,shared-libraries,Java,C++,Java Native Interface,Shared Libraries,我正在制作一种基于Java的编程语言,因为它有一个VM和一个语言到字节码编译器 实现该语言的特性,例如循环、变量、算术等的,对我来说不是问题;但是,像Java can这样执行本机函数是非常困难的 我需要本机函数,以使用我的语言编写的程序能够创建窗口、与硬件和操作系统接口,以及做任何不只是简单数学的事情 我听说了,它看起来确实是我想要的东西,但是,我不知道如何实现这样的东西 当我的VM在C++中实现时,我知道我可以在编译时把它包含在我的本机函数的 HPP文件中,然后它可以动态加载 DLL >或所以

我正在制作一种基于Java的编程语言,因为它有一个VM和一个语言到字节码编译器

实现该语言的特性,例如循环、变量、算术等的
,对我来说不是问题;但是,像Java can这样执行本机函数是非常困难的

我需要本机函数,以使用我的语言编写的程序能够创建窗口、与硬件和操作系统接口,以及做任何不只是简单数学的事情

我听说了,它看起来确实是我想要的东西,但是,我不知道如何实现这样的东西

当我的VM在C++中实现时,我知道我可以在编译时把它包含在我的本机函数的 HPP文件中,然后它可以动态加载<代码> DLL<代码> >或<代码>所以这似乎不是一个好的解决方案,因为每次您希望VM能够执行另一个本机函数时,都必须重新编译VM

问题是这样的:一个C++程序(VM)如何动态地(在运行时,由字节码指示,以更精确地)用C++函数加载库,然后执行这些函数而不在某些头文件中预先声明?

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

如何确定签名应该是什么取决于您的上下文。您可以根据参数类型推断大量调用。从显式Java接口、方法声明或动态调用参数推断本机调用签名

除了简单的函数调用之外,处理构造函数、内存管理和对象方法调度更为复杂,但仍然基于相同的基本原则。

请看。它提供了调用给定函数地址和调用签名的任何函数的方法

如何确定签名应该是什么取决于您的上下文。您可以根据参数类型推断大量调用。从显式Java接口、方法声明或动态调用参数推断本机调用签名


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

< P> >我所未曾讨论的一个主题是如何将来自新语言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 );
}
double result = eval_double( "libm", "pow", arg1, arg2 );
但这更糟糕。你仍然需要一个存根函数,你希望你的语言能够访问的C++函数。 听起来你想让你的语言有

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 );
}
double result = eval_double( "libm", "pow", arg1, arg2 );

我不知道如何在C++中实现这一点。VARGS支持获取任何类型的C++参数。但是没有任何API来推动任意类型的C++参数。

< P>一个我没有讨论过的主题是如何将新语言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 );
}
double result = eval_double( "libm", "pow", arg1, arg2 );
但这更糟糕。你仍然需要一个存根函数,你希望你的语言能够访问的C++函数。 听起来你想让你的语言有

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 );
}
double result = eval_double( "libm", "pow", arg1, arg2 );

我不知道如何在C++中实现这一点。VARGS支持获取任何类型的C++参数。但是没有任何API来推动任意类型的C++参数。< /P>你能提供一些代码示例吗?在Windows上,使用LoopRealBug()和GETPro()。Linux具有具有不同名称的等效函数。这些并不能帮助您知道参数的数量和类型以及返回值。@BhavikAmbani当然,几小时后我一回到家。@brianbeuning-我确实知道返回类型和参数的类型,因为该函数是用我的语言创建的,它与C/C++类型相当。可以在运行时声明函数吗?请提供一些您想要的代码示例吗?在Windows上使用LoadLibrary()和GetProcAddress()。Linux具有具有不同名称的等效函数。这些并不能帮助您知道参数的数量和类型以及返回值。@BhavikAmbani当然,几小时后我一回到家。@brianbeuning-我确实知道返回类型和参数的类型,因为该函数是用我的语言创建的,它与C/C++类型相当。有没有可能在运行时声明一个函数呢?这似乎是我需要的。但是,我不太确定如何在动态加载的共享对象(
dlopen()
)中获取指向函数的指针。我知道函数本身的名称、参数数量、参数类型和返回类型,因为这是用我的语言描述的,但我不确定如何获取指向本机函数的指针。如果我知道本机函数将被调用
X
,我可以得到指向它的指针吗?
dlsym()
查找给定名称的符号。通常导出的符号要么是可以调用的函数,要么是用于数据访问的全局变量的地址。现在我有了
dlopen()
dlsym()
,实际需要在哪里