@@ -574,35 +574,45 @@ static FUNC_UNUSED int obj_simple_udata_default_tostring(lua_State *L) {
574
574
return 1 ;
575
575
}
576
576
577
+ static int obj_constructor_call_wrapper (lua_State * L ) {
578
+ /* replace '__call' table with constructor function. */
579
+ lua_pushvalue (L , lua_upvalueindex (1 ));
580
+ lua_replace (L , 1 );
581
+
582
+ /* call constructor function with all parameters after the '__call' table. */
583
+ lua_call (L , lua_gettop (L ) - 1 , LUA_MULTRET );
584
+ /* return all results from constructor. */
585
+ return lua_gettop (L );
586
+ }
587
+
577
588
static void obj_type_register (lua_State * L , const obj_type_reg * type_reg ) {
578
589
const luaL_reg * reg_list ;
579
590
obj_type * type = type_reg -> type ;
580
591
const obj_base * base = type_reg -> bases ;
581
592
const obj_const * constants = type_reg -> constants ;
582
593
583
- /* create methods table. */
584
- lua_newtable (L );
585
- luaL_register (L , NULL , type_reg -> methods ); /* fill methods table. */
586
-
587
594
/* create public functions table. */
588
595
reg_list = type_reg -> pub_funcs ;
589
596
if (reg_list != NULL && reg_list [0 ].name != NULL ) {
590
- if (reg_list [1 ].name != NULL ) {
591
- lua_newtable (L );
592
- luaL_register (L , NULL , reg_list ); /* fill public functions table. */
593
- } else {
594
- lua_pushcfunction (L , reg_list [0 ].func ); /* push single 'new' function. */
595
- }
596
- /* register "public functions table" or "constructor" as '<object_name> */
597
+ /* register "constructors" as to object's public API */
598
+ luaL_register (L , NULL , reg_list ); /* fill public API table. */
599
+
600
+ /* make public API table callable as the default constructor. */
601
+ lua_newtable (L ); /* create metatable */
602
+ lua_pushliteral (L , "__call" );
603
+ lua_pushcfunction (L , reg_list [0 ].func ); /* push first constructor function. */
604
+ lua_pushcclosure (L , obj_constructor_call_wrapper , 1 ); /* make __call wrapper. */
605
+ lua_rawset (L , -3 ); /* metatable.__call = <default constructor> */
606
+ lua_setmetatable (L , -2 );
607
+
608
+ lua_pop (L , 1 ); /* pop public API table, don't need it any more. */
609
+ /* create methods table. */
610
+ lua_newtable (L );
597
611
} else {
598
- /* register "methods table" as '<object_name> */
599
- lua_pushvalue (L , -1 );
612
+ /* register all methods as public functions. */
600
613
}
601
- #if REG_OBJECTS_AS_GLOBALS
602
- lua_pushvalue (L , -1 ); /* dup value. */
603
- lua_setglobal (L , type -> name ); /* global: <object_name> = value */
604
- #endif
605
- lua_setfield (L , -3 , type -> name ); /* module["<object_name>"] = value */
614
+
615
+ luaL_register (L , NULL , type_reg -> methods ); /* fill methods table. */
606
616
607
617
luaL_newmetatable (L , type -> name ); /* create metatable */
608
618
lua_pushliteral (L , ".name" );
@@ -3282,11 +3292,24 @@ static const obj_type_reg obj_type_regs[] = {
3282
3292
3283
3293
3284
3294
3285
- int luaopen_git2 (lua_State * L ) {
3286
- const obj_type_reg * reg = obj_type_regs ;
3287
- /* module table. */
3288
- luaL_register (L , "git2" , git2_function );
3289
3295
3296
+
3297
+
3298
+
3299
+ static const luaL_Reg submodule_libs [] = {
3300
+ {NULL , NULL }
3301
+ };
3302
+
3303
+
3304
+
3305
+ static void create_object_instance_cache (lua_State * L ) {
3306
+ lua_pushlightuserdata (L , obj_udata_weak_ref_key ); /* key for weak table. */
3307
+ lua_rawget (L , LUA_REGISTRYINDEX ); /* check if weak table exists already. */
3308
+ if (!lua_isnil (L , -1 )) {
3309
+ lua_pop (L , 1 ); /* pop weak table. */
3310
+ return ;
3311
+ }
3312
+ lua_pop (L , 1 ); /* pop nil. */
3290
3313
/* create weak table for object instance references. */
3291
3314
lua_pushlightuserdata (L , obj_udata_weak_ref_key ); /* key for weak table. */
3292
3315
lua_newtable (L ); /* weak table. */
@@ -3296,12 +3319,35 @@ int luaopen_git2(lua_State *L) {
3296
3319
lua_rawset (L , -3 ); /* metatable.__mode = 'v' weak values. */
3297
3320
lua_setmetatable (L , -2 ); /* add metatable to weak table. */
3298
3321
lua_rawset (L , LUA_REGISTRYINDEX ); /* create reference to weak table. */
3322
+ }
3323
+
3324
+ int luaopen_git2 (lua_State * L ) {
3325
+ const obj_type_reg * reg = obj_type_regs ;
3326
+ const luaL_Reg * submodules = submodule_libs ;
3327
+ /* module table. */
3328
+ luaL_register (L , "git2" , git2_function );
3329
+
3330
+ /* create object cache. */
3331
+ create_object_instance_cache (L );
3332
+
3333
+ for (; submodules -> func != NULL ; submodules ++ ) {
3334
+ lua_pushcfunction (L , submodules -> func );
3335
+ lua_pushstring (L , submodules -> name );
3336
+ lua_call (L , 1 , 0 );
3337
+ }
3299
3338
3300
3339
/* register objects */
3301
- while (reg -> type != NULL ) {
3340
+ for (; reg -> type != NULL ; reg ++ ) {
3341
+ lua_newtable (L ); /* create public API table for object. */
3342
+ lua_pushvalue (L , -1 ); /* dup. object's public API table. */
3343
+ lua_setfield (L , -3 , reg -> type -> name ); /* module["<object_name>"] = <object public API> */
3344
+ #if REG_OBJECTS_AS_GLOBALS
3345
+ lua_pushvalue (L , -1 ); /* dup value. */
3346
+ lua_setglobal (L , reg -> type -> name ); /* global: <object_name> = <object public API> */
3347
+ #endif
3302
3348
obj_type_register (L , reg );
3303
- reg ++ ;
3304
3349
}
3350
+
3305
3351
return 1 ;
3306
3352
}
3307
3353
0 commit comments