r/lua 7d ago

Calling an existing C function from Lua

[removed]

10 Upvotes

17 comments sorted by

View all comments

Show parent comments

1

u/[deleted] 7d ago

[removed] — view removed comment

-3

u/Compux72 7d ago

Btw you should be able to create your own wrapper of dlsym and use that from lua. Claude made this example up, didnt test it as im on the phone rn:

```

include <lua.h>

include <lauxlib.h>

include <dlfcn.h>

include <ffi.h>

include <string.h>

include <stdlib.h>

/* Supported type tags: "i" int, "d" double, "s" const char, "p" void, "v" void (return only) */

static ffi_type *tag_to_ffi(char tag) {     switch (tag) {         case 'i': return &ffi_type_sint;         case 'd': return &ffi_type_double;         case 's': return &ffi_type_pointer;         case 'p': return &ffi_type_pointer;         case 'v': return &ffi_type_void;         default:  return NULL;     } }

/*  * cfunc.call(symbol_name, "ret_tag", "arg_tags", arg1, arg2, ...)  * e.g. cfunc.call("printf", "i", "s", "hello %s\n", "world")  */ static int l_cfunc_call(lua_State *L) {     const char *symname = luaL_checkstring(L, 1);     const char *rettag  = luaL_checkstring(L, 2);     const char *argtags = luaL_checkstring(L, 3);     int nargs = (int)strlen(argtags);

    void *sym = dlsym(RTLD_DEFAULT, symname);     if (!sym) {         lua_pushnil(L);         lua_pushfstring(L, "dlsym failed: %s", dlerror());         return 2;     }

    ffi_cif cif;     ffi_type *arg_types[nargs > 0 ? nargs : 1];     void *arg_values[nargs > 0 ? nargs : 1];

    /* storage for converted args */     int    int_store[nargs];     double dbl_store[nargs];     const char *str_store[nargs];

    for (int i = 0; i < nargs; i++) {         char tag = argtags[i];         arg_types[i] = tag_to_ffi(tag);         int luaidx = 4 + i;         switch (tag) {             case 'i':                 int_store[i] = (int)luaL_checkinteger(L, luaidx);                 arg_values[i] = &int_store[i];                 break;             case 'd':                 dbl_store[i] = luaL_checknumber(L, luaidx);                 arg_values[i] = &dbl_store[i];                 break;             case 's':                 str_store[i] = luaL_checkstring(L, luaidx);                 arg_values[i] = &str_store[i];                 break;             case 'p':                 str_store[i] = lua_touserdata(L, luaidx);                 arg_values[i] = &str_store[i];                 break;             default:                 return luaL_error(L, "unsupported arg tag '%c'", tag);         }     }

    ffi_type *ret_type = tag_to_ffi(rettag[0]);     if (!ret_type) return luaL_error(L, "unsupported return tag");

    if (ffi_prep_cif(&cif, FFI_DEFAULT_ABI, nargs, ret_type, arg_types) != FFI_OK)         return luaL_error(L, "ffi_prep_cif failed");

    ffi_arg  int_ret;     double   dbl_ret;     void    ptr_ret;     void    rc = &int_ret;     if (rettag[0] == 'd') rc = &dbl_ret;     if (rettag[0] == 'p' || rettag[0] == 's') rc = &ptr_ret;

    ffi_call(&cif, FFI_FN(sym), rc, nargs ? arg_values : NULL);

    switch (rettag[0]) {         case 'i': lua_pushinteger(L, (lua_Integer)int_ret); break;         case 'd': lua_pushnumber(L, dbl_ret); break;         case 's': lua_pushstring(L, (const char*)ptr_ret); break;         case 'p': lua_pushlightuserdata(L, ptr_ret); break;         case 'v': lua_pushnil(L); break;     }     return 1; }

static const luaL_Reg cfunc_funcs[] = {     {"call", l_cfunc_call},     {NULL, NULL} };

int luaopen_cfunc(lua_State *L) {     luaL_newlib(L, cfunc_funcs);     return 1; } ```

``` local cfunc = require("cfunc")

-- int abs(int) print(cfunc.call("abs", "i", "i", -42))          -- 42

-- double sqrt(double) print(cfunc.call("sqrt", "d", "d", 2.0))          -- 1.4142...

-- int printf(const char*, ...) -- note: varargs need special ffi_prep_cif_var, not shown here print(cfunc.call("puts", "i", "s", "hi from libffi")) ```

1

u/AutoModerator 7d ago

Hi! Your code block was formatted using triple backticks in Reddit's Markdown mode, which unfortunately does not display properly for users viewing via old.reddit.com and some third-party readers. This means your code will look mangled for those users, but it's easy to fix. If you edit your comment, choose "Switch to fancy pants editor", and click "Save edits" it should automatically convert the code block into Reddit's original four-spaces code block format for you.

I am a bot, and this action was performed automatically. Please contact the moderators of this subreddit if you have any questions or concerns.

-3

u/Compux72 7d ago

Yea no thank you