文字大小:

xlang5.1更新说明

xlang2025-08-10 20:35:12




编译器

  错误修复: 处理浮点数常量时, 改善两处有可能会造成问题的地方, 改善两处可能会因源代码存在语法错误而导致异常退出的问题。

虚拟机

  改动:

  1. 格式化浮点数时可能导致精度异常的一处 bug。

  2. 格式化浮点数时去掉了对小于1E-307精度部分的修正, 因此格式化浮点数时,字符串会显示浮点数本身存在的精度异常(见说明1)。

  3. 增加Math 类的 INT_MAX、INT_MIN、SHORT_MAX、SHORT_MIN、LONG_MAX、LONG_MIN常量,增加float类型的abs和min 、max方法。

  4. 对native调用进行了规范化(说明2).

  说明1:  

   例如 Math.FLOAT_MIN 的取值一般为1.175494351e-38F, 格式化时一般最大只支持到15位小数,因此 若使用 String 对其进行相加操作(如: "" + Math.FLOAT_MIN), 结果可能只是一个 0 , 所以需要使用String.format("%g", Math.FLOAT_MIN) ,则可得到字符串 "1.17549e-038"

  说明2:

   

在 xlang 中对其他语言例如C或者C++编写的dll 导出的C函数进行调用时需要特别几种类型 Pointer / ObjectPtr / ObjectRef / 和 * & (取地址及引用符号);

2.Pointer 类型.

      Pointer 为指针类型, 该类型一般用作兼容 64 位和32位系统的基本数据长度以及对对象取地址的数据类型。

      作用1,对参数对象取地址:

      当需要使用对象地址作为参数时,声明的参数类型应为 Pointer ,如C中的代码为: 

void Call(MyStruct * s);

      该方法参数为 MyStruct 类型的指针, 则在xlang 中的代码为:

// 如下声明
void Call(Pointer s);
//或者
void Call(MyStruct * s);
//或者
void Call(ObjectPtr s);

// 若有对象 MyStruct object;  则调用时的代码为
Call(object); // 此处直接填写对象名称,不可使用C中的 & 取地址符号, & 的作用看下文

      作用2:当需要进行 Native 调用的参数为 size_t  或者 void * 时, xlang 中声明的参数类型应为 Pointer, 此时 Pointer 类型可以与long类型兼容

如 C 中定义的方法原型如下:

      

size_t add(size_t a, size_t b);

xlang 中对应的声明应为 

Pointer add (Pointer a, Pointer b)

如此便可以使用一套程序同时兼容 64 位和32 位的调用。

需要注意的是,当 Pointer 仅作为 size_t 的替代品,无需取地址时,为了避免对参数对象取地址,应当使用一个long类型的临时变量作为参数传入。

2.ObjectPtr 类型

该种会自动对所有传入的对象进行取地址操作, 应与ObjectRef 类型区分,当DLL要求的参数是某个类型的指针时(而非xnl 中的XObject 对象指针), 可使用ObjectPtr 取地址, xlang中参数参数时,可不再使用取地址符号,但应注意不可对临时对象取地址,例如 (a + b) 产生的临时地址(编译器会提示错误), 完整举例如下:

DLL 中的 代码:

extern "C" void cdecl  func(int * p){
   *p = 1;
}

该方法要求传入一个int 指针,则xlang中的声明及使用:

第一种写法: void cdecl func(int * p);
或者 
第二种写法 : void cdecl func(ObjectPtr  p);

第一种写法在调用时需要像C语言中对参数使用 & 取地址, 例如

int a = 0;
func(&a);

第二种写法无需使用&,会自动取地址,如下:

int a;
func(a);

因此 ObjectPtr 是对所表示的其他语言中的对等数据类型取地址。

而 ObjectRef 不是为其他语言中的对等数据类型设计的,而是专为XNL接口中传递 xlang 中的元数据类型 XObject 设计的。

*需要明确的是,如果在参数中使用了成员对象表达式比如 a.b 或者数组 a[b], 那此表达式会先执行一次求值操作, 操作结果均为所求值的副本(不指向源对象地址), 那么无论是ObjectPtr 还是 *  Pointer(取地址), 都只是对结果的副本取地址,并不等于源对象地址,因此在进行取地址操作时会收到371警告[对临时对象的取地址或引用操作], 该警告指示参数中的表达式所得的值在一个临时对象中, 取地址操作将传入临时对象的指针, 可能造成错误 , 正确的做法应使用栈中变量进行取值传递, 需要回写的可在调用结束后回写.

*此设计的原因在于native层的读写操作是不安全的(可能存在由native->xvm的回溯调用改变原对象槽位上的数据\以及多线程问题),因此无法受到 vm 系统中 gc 的监管, 所以只有当对象在栈上时,方可安全进行.

此设计在后期进一步安全性评估可行的情况下有可能会进行改善,但本语言更着重于语言本身的安全和稳定性, 而非牺牲安全性为代价以期获得调用native模块的便利.

2.Native 方法的定义

需要给 Native 提供回调的方法需要声明为 @Native, 例如

@Native(CallConvention = "stdcall", Type = "Pointer")
    static Symbol_t EAController_getSymbol(String symbol, @Native(Type = "Pointer") Symbol_t st){
        return new Symbol_t(controller.getSymbol(symbol));
    }

说明: 该方法的返回值为Symbol_t 类型, Type 为Pointer , 说明对Native调用时的返回值为Symbol_t的结构体指针, 同时, 参数st 也是相同规则






上一篇:用 xlang 写一个在线反汇编的网站下一篇:xlang 5.2 更新日志

评论

写评论

点击刷新