Coder Social home page Coder Social logo

cffi-lua's People

Contributors

ffontaine avatar jan200101 avatar q66 avatar vsergeev avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

cffi-lua's Issues

Parameterized pointer type regression

local ffi = jit and require('ffi') or require('cffi')

ffi.cdef[[
typedef struct point {
    int x;
    int y;
} point_t;
]]

print(ffi.typeof("point_t")) --> ctype<struct point>
print(ffi.typeof("point_t *")) --> ctype<struct point *>
print(ffi.typeof("$ *", ffi.typeof("point_t"))) --> expected: ctype<struct point *>, get: ctype<struct point>

I'm expecting a pointer type for the parametrized typeof ffi.typeof("$ *", ffi.typeof("point_t"), but am getting the underlying structure type.

Running off of 07b30b0.

Build with prebuilt Lua Version

I am trying to build with a pre-build Lua version. meson was not able to find my Lua version. I then defined a lua.pc file:

`
prefix=/path/to/my/lua
exec_prefix=${prefix}
libdir=${exec_prefix}/lib
includedir=${prefix}/inc

Name: lua
Description: Lua programming language
Version: 5.3
Libs: -L${libdir} -llua
Cflags: -I${includedir}
`

I then get the following error:

Found pkg-config: C:\msys64\mingw32\bin/pkg-config.EXE (1.8.0)
Found CMake: C:\msys64\mingw32\bin/cmake.EXE (3.25.1)
Run-time dependency lua5.3 found: NO (tried pkgconfig and cmake)
Run-time dependency lua-5.3 found: NO (tried pkgconfig and cmake)
Run-time dependency lua53 found: NO (tried pkgconfig and cmake)
Run-time dependency lua found: YES 5.3
Run-time dependency libffi found: YES 3.4.4
Library dl found: NO
Computing int of "LUA_VERSION_NUM" with dependency lua: 503
Library lua found: NO
Library lua5.3 found: NO

../meson.build:144:8: ERROR: C++ shared or static library 'lua53' not found

the libdir already has lua53.dll file in there. After I renamed lua53.dll to lua.dll then that worked. But now it was not able to find the executable Lua.

So I made the deps subdirectory and put the lua53 executable and dll in there with all the include files in the deps/include subdirectory. Then I ran the command:

meson .. -Dlua_version=5.3 -Dlua_path=/path/to/cffi-lua-0.2.3/build/deps/lua.exe

that worked!

Now when I run ninja I get all fatal errors that it cannot find lua.hpp.

So I had to manually edit build.ninja to add the "-Ideps/include" term in the commands.
After that it worked.

Defining NDEBUG macro causes ffi.sizeof struct to return 0

Short background: remade the build system to work in conjuction with the rest of my system that builds Lua modules for a game. The build system for this game defines the macro NDEBUG for release builds.

While testing a build of this module with the NDEBUG macro, it was noticed that ffi.sizeof("struct something") was returning 0 (with this struct definition being struct something { int value; };). It will correctly return 4 if this macro is not defined. The host is a Linux x86_64 machine and it was built using GCC 9 (version doesn't matter).

I don't know if you will want to fix this issue but I'll use it as a heads-up for the future.

ensure no stack values with destructors are present in OOM scenarios

in the very rare case that lua OOMs and raises a panic case, we should ensure that no stack values (which could be managing heap pointers) with destructors are present, to avoid leaking memory or causing any state to go inconsistent

this specifically only affects places where lua APIs are called

Support metatable for ctype

It would be nice to have metatable support for ctypes themselves, as with the LuaJIT FFI:

local ffi = require('cffi')

ffi.cdef[[
typedef struct point {
    int x;
    int y;
} point_t;
]]

local mt = {
    __tostring = function (self)
        return string.format("Point<%d, %d>", self.x, self.y)
    end,
    __index = {
        from_array = function (arr)
            return ffi.new("point_t", arr[1], arr[2])
        end
    }
}

Point = ffi.metatype("point_t", mt)

print(Point(1, 2)) --> Point<1, 2>
print(Point.from_array({3, 4})) --> expected: Point<3, 4>, cffi-lua gives: 'ctype' is not indexable

This allows implementing static methods on the ctype, like alternate constructors, or utility functions namespaced under the ctype.

Support `char [N]` assignment from string

local ffi = jit and require('ffi') or require('cffi')

ffi.cdef[[
struct foo {
    char str[4];
};
]]

local f = ffi.new("struct foo")

f.str = "abc" --> expected: no error, get: "invalid C type"
print(ffi.string(f.str)) --> abc

f.str = "abcd1234"
print(ffi.string(f.str)) --> abcd

Structure element assignment by value through array or pointer

local ffi = jit and require('ffi') or require('cffi')

ffi.cdef[[
typedef struct point {
    int x;
    int y;
} point_t;
]]

local mt = {
    __tostring = function (self)
        return string.format("Point<%d, %d>", self.x, self.y)
    end,
}

Point = ffi.metatype("point_t", mt)

ffi.cdef[[
void *malloc(size_t size);
]]

local buf = ffi.C.malloc(ffi.sizeof(Point) * 32)
local points = ffi.cast(ffi.typeof("$ *", Point), buf)

points[0].x = 1
points[0].y = 2
print(points[0]) --> Point<1, 2>

print(Point(1, 2)) --> Point<1, 2>

points[0] = Point(1, 2) --> expected: no error, get: cannot convert 'struct point' to 'struct point'
print(points[0]) --> Point<1, 2>

Error occurs when assigning a structure array element by value through a pointer. Same error occurs for assignment through a fixed size array, e.g. local points = ffi.new("point_t [32]").

__new metamethod never called

local ffi = require("cffi")

local S = ffi.metatype("struct { int x; }", {
   __new = function(ct, x)
      error("__new Called")
      return ffi.new(ct, x or 0)
   end,
})

local s = S()

Expected is that this test case to raise an error if the library is to operate similar to LuaJIT and as described in semantics.md. However it returns without error.

This is the output on LuaJIT (with require("ffi"))

luajit: test.lua:5: __new called
stack traceback:
	[C]: in function 'error'
	test.lua:5: in function 'S'
	test.lua:10: in main chunk
	[C]: at 0x5facfc7a2cd0

Type comparison (istype) differs from LuaJIT

Hello,

Thank your for your help on the previous issue.

this one might be intended? I came across the following difference between LuaJIT/ffi and cffi:

local ffi = jit and require('ffi') or require('cffi')

ffi.cdef([[
struct structure {
    double scalar;
    double vector[3];
};
]])

local structure = ffi.new('struct structure')
print(ffi.istype('double [3]', structure.vector))
print(ffi.istype('double (&)[3]', structure.vector))

the last istype returns true with LuaJIT/ffi but false with cffi, i.e. double [3] and double (&)[3] are considered as the same type in one case but different types in the second case.

get rid of malloc and abort usage

All allocations in the system should be done through Lua's allocator. Also, we should never abort, instead access to lua_State state should be ensured at all times in those contexts and a Lua error should be raised.

Create a meson subproject wrap file for libffi

I was compiling libffi on windows and I wasn't able to compile it. After searching through some issues and pull requests I found out that there is a PR which adds meson build support to libffi. You may consider it adding to cffi-lua.

subprojects/libffi.wrap

I think this is more stable.

[wrap-git]
url = https://gitlab.freedesktop.org/gstreamer/meson-ports/libffi.git
revision = meson
depth = 1

[provide]
ffi = ffi_dep

Or add gitlab rebased version with latest libffi.

[wrap-git]
url = https://github.com/xclaesse/libffi.git
revision = meson-port
depth = 1

[provide]
ffi = ffi_dep

https://github.com/q66/cffi-lua/blob/master/meson.build#L78-L85

ffi_dep = subproject('libffi').get_variable('ffi_dep')

Support struct array element assignment from dereferenced const pointer

local ffi = jit and require('ffi') or require('cffi')

ffi.cdef[[
typedef struct point {
    int x;
    int y;
} point_t;
]]

local points1 = ffi.new("point_t[4]")
local points2 = ffi.new("point_t[4]")

local cpoints2 = ffi.cast("const point_t *", points2)

print(points1[0].x, points1[0].y) --> 0 0

points2[0].x = 1
points2[0].y = 2

points1[0] = cpoints2[0] --> expected: no error, get: cannot convert 'struct point' to 'struct point'

print(points1[0].x, points1[0].y) --> 1 2

Instructions to build with MSVC

Maybe this will save someone some headache

  1. Get python version 3 in PATH. I just happened to have 3.11, no issues
  2. Get meson. Docs don't specify the version but the project won't build with version <0.64.
    For this I used vcpkg from Git Bash:
    cd /c/vcpkg
    git pull
    ./bootstrap-vcpkg.sh
    # if you have one installed but it is old
    ./vcpkg remove vcpkg-tool-meson --recurse
    ./vcpkg install vcpkg-tool-meson
  3. Do not use libffi from vcpkg since it is a DLL not a static lib
  4. Make cffi/deps folder and put whatever the docs say you need to put there. I've put this tree there
    lua53.dll
    lua53.lib
    lua53.exe
    include\lauxlib.h
    include\lua.h
    include\luaconf.h
    include\lualib.h
    include\lua.hpp
  5. mkdir cffi/build
  6. Now open a developer command prompt from Visual Studio in this folder and do this for default buildtype (debugoptimized). Use your paths. Git is needed to grab libffi. --skip-subprojects is needed to not install it since it is a static lib.
    set PATH=C:\Work\Tools\Git\bin;%PATH%
    python c:\vcpkg\downloads\tools\meson-1.3.2-d646d3\meson.py setup .. -Dlua_version=vendor -Dlua_install_path=c:\Work\Tools\qlua\lib\lua\@0@\debug
    ninja all
    ninja test
    python c:\vcpkg\downloads\tools\meson-1.3.2-d646d3\meson.py install --skip-subprojects
  7. This got installed
    Installing cffi.dll to c:\Work\Tools\qlua\lib\lua\5.3\debug
    Installing cffi.lib to c:\Work\Tools\qlua\lib\lua\5.3\debug
    Installing cffi.pdb to c:\Work\Tools\qlua\lib\lua\5.3\debug
    
  8. For a release build do this instead:
    set PATH=C:\Work\Tools\Git\bin;%PATH%
    python c:\vcpkg\downloads\tools\meson-1.3.2-d646d3\meson.py setup .. -Dlua_version=vendor -Dlua_install_path=c:\Work\Tools\qlua\lib\lua\@0@ -Dbuildtype=release
    ninja all
    ninja test
    python c:\vcpkg\downloads\tools\meson-1.3.2-d646d3\meson.py install --tags runtime
  9. This will get installed Installing cffi.dll to c:\Work\Tools\qlua\lib\lua\5.3

MetaType __len not working correctly

I'm trying to duplicate the following code from luajit ffi

local cffi = require("cffi")
cffi.cdef[[
typedef struct { double x, y; } point_t;
]]

local point
local mt = {
  __add = function(a, b) return point(a.x+b.x, a.y+b.y) end,
  __len = function(a) return math.sqrt(a.x*a.x + a.y*a.y) end,
  __index = {
    area = function(a) return a.x*a.x + a.y*a.y end,
  },
}
point = cffi.metatype("point_t", mt)

local a = point(3, 4)
print(a.x, a.y)  --> 3  4
print(#a)        --> 5
print(a:area())  --> 25
local b = a + point(0.5, 8)
print(#b)        --> 12.5

Everything works with the exception of __len. when the code reaches print(#a) I get the error 'struct 0' is not callable.

__add and __index both work fine if I remove the code using __len Tried on macos and Windows.

Interaction between cffi and lgi causes crashes

Hi, please see the below code for demo.

-- Uncommenting the line below will introduce a crash in callback:free().
require("cffi")
local lgi = require("lgi")
local callback = require("cffi").cast("void (*)()", function() end)
print("Before free")
callback:free()
print("After free")

I'm using cffi from luarocks, lua 5.1, and lgi from Debian repo (unstable).

env: ‘./luarocks/build.sh’: Permission denied

When I try:

luarocks install --local cffi-lua

I get:

Installing https://rocks.moonscript.org/cffi-lua-0.1.1-1.src.rock...
Using https://rocks.moonscript.org/cffi-lua-0.1.1-1.src.rock... switching to 'build' mode
env \
        LUA="lua" CC="gcc" LD="gcc" \
        CFLAGS='-O2 -fPIC -I/usr/include -I/usr/include' \
        LDFLAGS='-L/usr/lib -lffi' \
        PREFIX="/home/me/.luarocks/lib/luarocks/rocks/cffi-lua/0.1.1-1" LIBDIR="/home/me/.luarocks/lib/luarocks/rocks/cffi-lua/0.1.1-1/lib" \
        ./luarocks/build.sh build

env: ‘./luarocks/build.sh’: Permission denied

Error: Build error: Failed building.

Support passing pointer for array argument

local ffi = jit and require('ffi') or require('cffi')

ffi.cdef[[
    int pipe(int fildes[2]);
]]

--[[
-- also:
local buf = ffi.new('int [2]')
local pipe_fds = ffi.cast('int *', buf)
]]--

local pipe_fds = ffi.new('int [2]')
ffi.C.pipe(pipe_fds) --> expected: no error, get: cannot convert 'int *' to 'int [2]'
print(pipe_fds[0]) --> 3
print(pipe_fds[1]) --> 4

It appears that cdata<T [N]> and cdata<T *> types cannot be passed as an argument to a function expecting T [N].

Support passing struct by value

local ffi = jit and require('ffi') or require('cffi')

--[[
/* testlib.c */
/* gcc -shared testlib.c -o testlib.so */
#include <stdio.h>

struct foo {
    int a;
    int b;
};

void print_foo(struct foo x) {
    printf("foo<%d, %d>\n", x.a, x.b);
}

void print_const_foo(const struct foo x) {
    printf("foo<%d, %d>\n", x.a, x.b);
}
]]--

ffi.cdef[[
struct foo {
    int a;
    int b;
};

void print_foo(struct foo x);
void print_const_foo(const struct foo x);
]]

local testlib = ffi.load('./testlib.so')

local foo = ffi.new("struct foo", 1, 2)

testlib.print_foo(foo) --> expected: foo<1, 2>, get: cannot convert 'struct foo' to 'struct foo'
testlib.print_const_foo(foo) --> expected: foo<1, 2>, get: cannot convert 'struct foo' to 'struct foo'

ffi.h not found

Since I couldn't get luarocks install --local cffi-lua to work (see Issue 3), I tried:

luarocks unpack cffi-lua
cd cffi-lua/cffi-lua-0.1.1-1/cffi-lua
luarocks make --local cffi-lua-0.1.1-1.rockspec

and then get an error about ffi.h not being found (see full log below), despite me having libffi installed and ffi.h residing in /usr/lib64/libffi-3.2.1/include/ffi.h.

I'm this build on amd64 Gentoo Linux.

Here's the full build log:

%  luarocks make --local cffi-lua-0.1.1-1.rockspec
env \
        LUA="lua" CC="gcc" LD="gcc" \
        CFLAGS='-O2 -fPIC -I/usr/include -I/usr/include' \
        LDFLAGS='-L/usr/lib -lffi' \
        PREFIX="/home/me/.luarocks/lib/luarocks/rocks/cffi-lua/0.1.1-1" LIBDIR="/home/me/.luarocks/lib/luarocks/rocks/cffi-lua/0.1.1-1/lib" \
        ./luarocks/build.sh build

The Meson build system
Version: 0.50.1
Source dir: /home/me/test/lua/cffi-lua/cffi-lua-0.1.1-1/cffi-lua
Build dir: /home/me/test/lua/cffi-lua/cffi-lua-0.1.1-1/cffi-lua/build
Build type: native build
Project name: cffi-lua
Project version: 0.1.1
Appending CXXFLAGS from environment: '-O2 -fPIC -I/usr/include -I/usr/include'
Appending LDFLAGS from environment: '-L/usr/lib -lffi'
Native C++ compiler: g++ (gcc 8.2.0 "g++ (Gentoo 8.2.0-r6 p1.7) 8.2.0")
Build machine cpu family: x86_64
Build machine cpu: x86_64
Compiler for C++ supports arguments -Wshadow: YES
Compiler for C++ supports arguments -Wold-style-cast: YES
Compiler for C++ supports arguments -fvisibility=hidden: YES
Checking for size of "void *" : 8
Has header "endian.h" : YES
Library dl found: YES
Has header "ffi.h" with dependency not-found: NO
Has header "ffi/ffi.h" with dependency not-found: NO

meson.build:109:8: ERROR: Problem encountered: libffi header file not found

A full log can be found at /home/me/test/lua/cffi-lua/cffi-lua-0.1.1-1/cffi-lua/build/meson-logs/meson-log.txt

Error: Build error: Failed building.

Support passing string to `const void *`

local ffi = jit and require('ffi') or require('cffi')

ffi.cdef[[
    //typedef intptr_t ssize_t;
    ssize_t write(int fd, const void *buf, size_t count);
]]

local s = "hello world\n"
ffi.C.write(1, s, #s) --> expected: no error, get: cannot convert 'string' to 'void const *'

The LuaJIT FFI will happily cast a string to a const void * (but not to void *, understandably), which is useful for interacting with C functions dealing with byte strings (e.g. file descriptor I/O, sockets, etc.). cffi-lua doesn't support this without an explicit cast ffi.cast('const void *', s).

Switch build system to XMake?

Right now I can't install this via LuaRocks because Meson isn't installed on our systems. Furthermore, adding cffi-lua as a dependency makes Meson a transitive dependency for building my library.

I was wondering if it'd be possible to switch over to using xmake as the build system? It'll provide a number of advantages:

  • There's a LuaRocks plugin you can add as a build-time dependency that'll automatically install it if it's not available. This means that users don't need to install XMake themselves.
  • XMake's configuration is literally just plain Lua.
  • You can use XMake's package management to install libffi if it's not installed already.
  • XMake is cross-platform.

This means that all users need to install cffi-lua is some version of Lua, an appropriate C++ compiler, and either XMake or LuaRocks depending on how they're installing it.

Issues building on Debian for armhf

Hi There,

I have built this one on an armhf environment, together with Lua 5.3.6.
All seems to build fine, but when I try to do:

local cffi = require("cffi")

I get an error message:

lua: error loading module 'cffi' from file '/usr/local/lib/lua/5.3/cffi.so':
        /usr/local/lib/lua/5.3/cffi.so: unexpected reloc type 0x03

The process I am following is:
. Extract lua5.3.6
. build lua with make linux && make install
. then build cffi using -Dlua_version=vendor (I have copied the relevant files to deps folder)

cffi.so builds with no error, but gives me the message above when I try to use it.

I have no idea of what can be the issue, though I have a feeling it might be something simple I am missing.
Any help would be much appreciated.

Thanks,
Marcelo.

Anonymous enum definition regression

local ffi = jit and require('ffi') or require('cffi')

ffi.cdef[[
    enum {FOO = 1};
    enum {BAR = 2};
]]

ffi.cdef[[
    enum {QUX = 3};
]] -- expected: no error, get: input:1: 'enum 3' redefined

Introduced in a335870.

Release version 0.2.0

The amount of fixes since last release has been massive, so it's time to spin a new one.

Current TODO

Support redefining nested anonymous struct within anonymous struct

local ffi = jit and require('ffi') or require('cffi')

ffi.cdef[[
    typedef struct {
        struct {
            uint32_t a;
        } inner1;
    } foo_t;

    typedef struct {
        struct {
            uint32_t b;
        } inner2;
    } bar_t;
]] -- expected: no error, get: input:1: 'struct 0' redefined

print(ffi.new("foo_t")) --> cdata<struct 95>: 0x40e88a78
print(ffi.new("bar_t")) --> cdata<struct 100>: 0x40e88b40

cffi-lua raises an error when redefining a nested anonymous struct within an anonymous struct. This is problematic in a codebase where two typedef anonymous structures happen to share a nested anonymous structure by sheer coincidence.

Note, however, redefinition of the nested anonymous structure is OK if the parent structure is named:

ffi.cdef[[
    struct foo {
        struct {
            uint32_t a;
        } inner1;
    };

    struct bar {
        struct {
            uint32_t b;
        } inner2;
    };
]] 

segfaults in ffi::newctype

Hello,

thank you for the previous patches.

I am currently stuck with the following issue. When running a "complex" program at some point I get segfaults in ffi::newctype. Below is a typical example of a trace obtained with gdb:

#0  0x0000555555564385 in sweeplist ()
#1  0x0000555555564475 in sweepstep ()
#2  0x00005555555658b4 in singlestep ()
#3  0x0000555555566020 in luaC_step ()
#4  0x000055555555e137 in lua_newuserdatauv ()
#5  0x00007ffff73fb4db in operator new (n=40, L=0x5555557942a8) at ../src/lua.hh:158
#6  0x00007ffff73fa83e in ffi::newctype<ast::c_type>(lua_State *, <unknown type in lib/lua/5.4/cffi.so, CU 0xca9, DIE 0x51d2>) (
    L=0x5555557942a8, args#0=<unknown type in lib/lua/5.4/cffi.so, CU 0xca9, DIE 0x51d2>) at ../src/ffi.hh:282
...

Unfortunately I could not reproduce this issue with a minimal example. The segfaults happen in several of my use cases and are always triggered by the previous sequence: ffi::newctype/sweeplist. It does not happen on the first call to ffi::newctype but rather after O(100) calls or so.

Sorry, this is not very helpful but I don't know what to check at this point? Please, let me know if there are extra values that would be meaningful to be printed out, e.g. using gdb?

When using LuaJIT/ffi I have no segfaults.

Support struct array element assignment from table

local ffi = jit and require('ffi') or require('cffi')

ffi.cdef[[
typedef struct point {
    int x;
    int y;
} point_t;
]]

local points = ffi.new("point_t[4]")

points[0] = {1, 2} --> expected: no error, get: cannot convert 'table' to 'struct point'

print(points[0].x, points[0].y) --> 1 2

I don't actually use this one, but happened to stumble across it. I didn't realize the LuaJIT FFI allowed it.

How much compatibility is wanted?

Hi there q66,

Sorry its me again.
I do not know how compatible you want to be with the luajit ffi, but here's a test code which gave me issues:

local cffi = require("cffi")
cffi.cdef[[

typedef uint8_t Uint8;
typedef uint32_t Uint32;

typedef struct Device
{
    int needed;
    Uint8 *buf;
    Uint32 len;
} __attribute__((packed)) Device;

enum
{
    SDL_PIXELFORMAT_YV12 =
        ((((Uint32)(((Uint8)(('Y'))))) << 0) | (((Uint32)(((Uint8)(('V'))))) << 8) | (((Uint32)(((Uint8)(('1'))))) << 16) | (((Uint32)(((Uint8)(('2'))))) << 24)),
    SDL_PIXELFORMAT_IYUV =
        ((((Uint32)(((Uint8)(('I'))))) << 0) | (((Uint32)(((Uint8)(('Y'))))) << 8) | (((Uint32)(((Uint8)(('U'))))) << 16) | (((Uint32)(((Uint8)(('V'))))) << 24)),
    SDL_PIXELFORMAT_YUY2 =
        ((((Uint32)(((Uint8)(('Y'))))) << 0) | (((Uint32)(((Uint8)(('U'))))) << 8) | (((Uint32)(((Uint8)(('Y'))))) << 16) | (((Uint32)(((Uint8)(('2'))))) << 24)),
    SDL_PIXELFORMAT_UYVY =
        ((((Uint32)(((Uint8)(('U'))))) << 0) | (((Uint32)(((Uint8)(('Y'))))) << 8) | (((Uint32)(((Uint8)(('V'))))) << 16) | (((Uint32)(((Uint8)(('Y'))))) << 24)),
    SDL_PIXELFORMAT_YVYU =
        ((((Uint32)(((Uint8)(('Y'))))) << 0) | (((Uint32)(((Uint8)(('V'))))) << 8) | (((Uint32)(((Uint8)(('Y'))))) << 16) | (((Uint32)(((Uint8)(('U'))))) << 24))
};

int printf(const char *fmt, ...);
]]
cffi.C.printf("Hello %s!\n", "world")

This code, ported from a luajit ffi code, gives me errors on lines 10 and 17.
I can probably fix that manually, just wanted to know if this is something you expect to happen or if it is really bugs you want reported.

Thanks,
Marcelo.

help with libcurl

I tried to use libcurl with cffi.
It's fine in luajit. but with puc it give error
libc: Fatal signal 11 (SIGSEGV), code 2 (SEGV_ACCERR), fault addr 0x7ac9a706e0 in tid 27717 (lua), pid 27717 (lua)

the problem is when doing curl_callback.

Also without this line in luajit also give strange incomplete result. maybe it's important to redefine the built-in typedefs which cffi fail to compile.

typedef int64_t time_t;
typedef unsigned int size_t;
local curl = require("libcurl-ffi")
-- local curl = require("luajit-curl")
local ffi = require"ffi" or require"cffi"

local ch = curl.curl_easy_init()

function curl_callback(callfunc)
  return ffi.cast("curl_callback", function (ptr, size, nmemb, stream)
  	local bytes = size*nmemb
  	local dst = ffi.new("char[?]", size*nmemb)
  	ffi.copy(dst, ptr, size*nmemb)
  	callfunc(ffi.string(dst, size*nmemb))
  	return bytes
  end)
end
if (ch) then
	curl.curl_easy_setopt(ch, curl.CURLOPT_URL, "http://example.com")
	curl.curl_easy_setopt(ch, curl.CURLOPT_FOLLOWLOCATION, 1)

  local raw_body = {}
  local raw_header = {}

	local clb_write = curl_callback(function(s) table.insert(raw_body, s) end)
	local clb_header = curl_callback(function(s) table.insert(raw_header, s) end)

	curl.curl_easy_setopt(ch, curl.CURLOPT_WRITEFUNCTION, clb_write)
	curl.curl_easy_setopt(ch, curl.CURLOPT_HEADERFUNCTION, clb_header)
		
	local success, err = pcall(function()
		return curl.curl_easy_perform(ch)
	end)
	clb_write:free()
	clb_header:free()
	
	print(success, err)
	
	-- local result = curl.curl_easy_perform(ch)
	-- if (result ~= curl.CURLE_OK) then
		-- print("FAILURE:", ffi.string(curl.curl_easy_strerror(result)))
	-- end
	
	if #raw_header>0 then
	  print(table.concat(raw_header))
	end
	print("bodylen:", #raw_body)

	curl.curl_easy_cleanup(ch)
	
	print("final>")
end

test_curl.lua.txt
libcurl-ffi.lua.txt

Support passing string through `ffi.string()`

local ffi = jit and require('ffi') or require('cffi')

local s = "hello world"
print(ffi.string(s)) --> expected: "hello world", get: bad argument #1 to 'string' (cannot convert 'string' to 'char const *')

LuaJIT FFI allows passing a string argument through ffi.string().

Problem with simple "typedef"

When copying from a LuaJit.FFI interface, in order to get the CFFI version working I had to remove simple typedefs like

typedef long type_t;

and use the long instead. This is the CFFI error msg I get with typedef declarations:

input:1: ';' expected near 'time_t'

Any hope this can be integrated with CFFI? (... or am I doing something wrong; couldn't find an example or test using it.)

windows build issues

Hello guys

Trying to build cffi-lua for windows x64. Prior to this have built lua (dll, lib, compirer and interpreter). Downloaded cffi-lua sources using MCVS 2022. Istalled Meson / Python etc

When trying ti build using meson / ninja a have got multiple issues, some of them I was able to resolve but not all. Please help.

c:\Users\79151\source\repos\cffi-lua\build>meson .. -Dlua_version=5.4 -Dlibffi=vendor
The Meson build system
Version: 1.0.0
Source dir: C:\Users\79151\source\repos\cffi-lua
Build dir: C:\Users\79151\source\repos\cffi-lua\build
Build type: native build
Project name: cffi-lua
Project version: 0.2.3
C++ compiler for the host machine: cl (msvc 19.34.31937 "��⨬������騩 ��������� Microsoft (R) C/C++ ���ᨨ 19.34.31937 ��� x64")
C++ linker for the host machine: link link 14.34.31937.0
Host machine cpu family: x86_64
Host machine cpu: x86_64
Compiler for C++ supports arguments -Wshadow: NO
Compiler for C++ supports arguments -Wold-style-cast: NO
Did not find pkg-config by name 'pkg-config'
Found Pkg-config: NO
Found CMake: C:\Program Files\Microsoft Visual Studio\2022\Community\Common7\IDE\CommonExtensions\Microsoft\CMake\CMake\bin\cmake.EXE (3.24.202208181)
Run-time dependency lua5.4 found: NO (tried pkgconfig and cmake)
Run-time dependency lua-5.4 found: NO (tried pkgconfig and cmake)
Run-time dependency lua54 found: NO (tried pkgconfig and cmake)
Run-time dependency lua found: YES 5.4.4
Library ffi found: YES
Library dl found: NO
Computing int of "LUA_VERSION_NUM" with dependency lua: 504
Library lua found: NO
Library lua5.4 found: NO
Library lua54 found: YES
Program lua54 found: YES (C:\Program Files\Lua54\lua54.EXE)
WARNING: You should add the boolean check kwarg to the run_command call.
It currently defaults to false,
but it will default to true in future releases of meson.
See also: mesonbuild/meson#9300
Build targets in project: 2
NOTICE: Future-deprecated features used:

  • 0.56.0: {'meson.build_root', 'meson.source_root'}

cffi-lua 0.2.3

User defined options
libffi : vendor
lua_version: 5.4

Found ninja-1.11.1 at "C:\Program Files\Meson\ninja.EXE"
WARNING: Running the setup command as meson [options] instead of meson setup [options] is ambiguous and deprecated.

c:\Users\79151\source\repos\cffi-lua\build>ninja all
[1/10] Compiling C++ object cffi.dll.p/src_ast.cc.obj
FAILED: cffi.dll.p/src_ast.cc.obj
"cl" "-Icffi.dll.p" "-I." "-I.." "-I..\deps\include" "/MD" "/nologo" "/showIncludes" "/utf-8" "/Zc:__cplusplus" "/W4" "/EHs-c-" "/GR-" "/std:c++14" "/permissive-" "/O2" "/Zi" "-DCFFI_LUA_DLL" "-DFFI_LITTLE_ENDIAN" "/Fdcffi.dll.p\src_ast.cc.pdb" /Focffi.dll.p/src_ast.cc.obj "/c" ../src/ast.cc
c:\Users\79151\source\repos\cffi-lua\src\lua.hh(23): fatal error C1083: Не удается открыть файл включение: lua.hpp: No such file or directory,
[4/10] Compiling C++ object cffi.dll.p/src_ffilib.cc.obj
FAILED: cffi.dll.p/src_ffilib.cc.obj
"cl" "-Icffi.dll.p" "-I." "-I.." "-I..\deps\include" "/MD" "/nologo" "/showIncludes" "/utf-8" "/Zc:__cplusplus" "/W4" "/EHs-c-" "/GR-" "/std:c++14" "/permissive-" "/O2" "/Zi" "-DCFFI_LUA_DLL" "-DFFI_LITTLE_ENDIAN" "/Fdcffi.dll.p\src_ffilib.cc.pdb" /Focffi.dll.p/src_ffilib.cc.obj "/c" ../src/ffilib.cc
c:\Users\79151\source\repos\cffi-lua\src\lua.hh(23): fatal error C1083: Не удается открыть файл включение: lua.hpp: No such file or directory,
[5/10] Compiling C++ object cffi.dll.p/src_lib.cc.obj
FAILED: cffi.dll.p/src_lib.cc.obj
"cl" "-Icffi.dll.p" "-I." "-I.." "-I..\deps\include" "/MD" "/nologo" "/showIncludes" "/utf-8" "/Zc:__cplusplus" "/W4" "/EHs-c-" "/GR-" "/std:c++14" "/permissive-" "/O2" "/Zi" "-DCFFI_LUA_DLL" "-DFFI_LITTLE_ENDIAN" "/Fdcffi.dll.p\src_lib.cc.pdb" /Focffi.dll.p/src_lib.cc.obj "/c" ../src/lib.cc
c:\Users\79151\source\repos\cffi-lua\src\lua.hh(23): fatal error C1083: Не удается открыть файл включение: lua.hpp: No such file or directory,
[6/10] Compiling C++ object cffi.dll.p/src_parser.cc.obj
FAILED: cffi.dll.p/src_parser.cc.obj
"cl" "-Icffi.dll.p" "-I." "-I.." "-I..\deps\include" "/MD" "/nologo" "/showIncludes" "/utf-8" "/Zc:__cplusplus" "/W4" "/EHs-c-" "/GR-" "/std:c++14" "/permissive-" "/O2" "/Zi" "-DCFFI_LUA_DLL" "-DFFI_LITTLE_ENDIAN" "/Fdcffi.dll.p\src_parser.cc.pdb" /Focffi.dll.p/src_parser.cc.obj "/c" ../src/parser.cc
c:\Users\79151\source\repos\cffi-lua\src\lua.hh(23): fatal error C1083: Не удается открыть файл включение: lua.hpp: No such file or directory,
[7/10] Compiling C++ object cffi.dll.p/src_main.cc.obj
FAILED: cffi.dll.p/src_main.cc.obj
"cl" "-Icffi.dll.p" "-I." "-I.." "-I..\deps\include" "/MD" "/nologo" "/showIncludes" "/utf-8" "/Zc:__cplusplus" "/W4" "/EHs-c-" "/GR-" "/std:c++14" "/permissive-" "/O2" "/Zi" "-DCFFI_LUA_DLL" "-DFFI_LITTLE_ENDIAN" "/Fdcffi.dll.p\src_main.cc.pdb" /Focffi.dll.p/src_main.cc.obj "/c" ../src/main.cc
c:\Users\79151\source\repos\cffi-lua\src\lua.hh(23): fatal error C1083: Не удается открыть файл включение: lua.hpp: No such file or directory,
[8/10] Compiling C++ object cffi.dll.p/src_ffi.cc.obj
FAILED: cffi.dll.p/src_ffi.cc.obj
"cl" "-Icffi.dll.p" "-I." "-I.." "-I..\deps\include" "/MD" "/nologo" "/showIncludes" "/utf-8" "/Zc:__cplusplus" "/W4" "/EHs-c-" "/GR-" "/std:c++14" "/permissive-" "/O2" "/Zi" "-DCFFI_LUA_DLL" "-DFFI_LITTLE_ENDIAN" "/Fdcffi.dll.p\src_ffi.cc.pdb" /Focffi.dll.p/src_ffi.cc.obj "/c" ../src/ffi.cc
c:\Users\79151\source\repos\cffi-lua\src\lua.hh(23): fatal error C1083: Не удается открыть файл включение: lua.hpp: No such file or directory,
ninja: build stopped: subcommand failed.

c:\Users\79151\source\repos\cffi-lua\build>

In the subdirectory deps I have lua and ffi libs that I was able to build somehow

18.01.2023 11:30

.
18.01.2023 11:30 ..
18.01.2023 11:29 32 256 ffi-8.dll
18.01.2023 11:29 8 140 ffi.lib
18.01.2023 11:35 include
18.01.2023 00:15 18 432 lua.exe
18.01.2023 00:06 299 520 lua54.dll
18.01.2023 00:06 30 278 lua54.lib
5 файлов 388 626 байт

c:\Users\79151\source\repos\cffi-lua\deps>

Parse constants like luajit-ffi

Hello !
Nice work !
While doing some tests with existing luajit-ffi files I noticed that cffi do not understand this declarations as constants like enums:

/* kind of structural variable: */
static const int GLP_CV=  1;  /* continuous variable */
static const int GLP_IV = 2;  /* integer variable */
static const int GLP_BV=  3;  /* binary variable */

Cheers !

Support additional C type serialization with `ffi.string()`

local ffi = jit and require('ffi') or require('cffi')

local buf = ffi.new("uint8_t [3]", {0x61, 0x62, 0x63})
local p = ffi.cast("const uint8_t *", buf)

print(ffi.string(buf, ffi.sizeof(buf))) --> expected: abc, get: bad argument #1 to 'string' (cannot convert 'unsigned char [3]' to 'string')
print(ffi.string(p, 3)) --> expected: abc, get: bad argument #1 to 'string' (cannot convert 'unsigned char const *' to 'string')

ffi.cdef[[
struct foo {
    uint8_t a;
};
]]

local s = ffi.new("struct foo", 0x61)
local p = ffi.cast("const struct foo *", buf)

print(ffi.string(s, ffi.sizeof(s))) --> expected: a, get: bad argument #1 to 'string' (cannot convert 'struct foo' to 'string')
print(ffi.string(p, 1)) --> expected: a, get: bad argument #1 to 'string' (cannot convert 'struct foo *' to 'string')

[Question] C++14 vs ANSI C

First of all, thank you very much for the library, it's awesome!

Any reason to implement it using C++14 instead of ANSI C like the Lua language?

`unsigned short int` throws an error

Hello 👋

So, I have a problem with defiining an unsigned short int.
In LuaJIT's ffi, defining unsigned short int does valid, but in cffi-lua, it throws an error.

local cffi = require 'cffi'

cffi.cdef[[
unsigned short int myInt; // <-- Error/Invalid 
unsigned int myOtherInt; // <-- Valid
]]

Failing FFI example

Hi! Thanks for this lib. Here's some code that I'm porting that implements a ring buffer. It errors on cffi but not luajit/other pure lua ffi implementations:

-- Use of this source code is governed by the Apache 2.0 license; see COPYING.

-- Ring buffer for bytes

local test_ffi_lib = 'ffi' -- 'cffi' or 'ffi'

local ffi = require(test_ffi_lib)
local bit = require("bit32")

local band = bit.band

ffi.cdef [[
   typedef struct {
      uint32_t read_idx, write_idx;
      uint32_t size;
      uint8_t buf[?];
   } buffer_t;
]]

local function to_uint32(n)
   return ffi.new('uint32_t[1]', n)[0]
end

local function new(size)
   local ret = buffer_t(size)
   ret:init(size)
   return ret
end

local buffer = {}
buffer.__index = buffer

function buffer:init(size)
   assert(size ~= 0 and band(size, size - 1) == 0, "size not power of two")
   self.size = size
   return self
end

function buffer:reset()
   self.write_idx, self.read_idx = 0, 0
end

function buffer:is_empty()
   return self.write_idx == self.read_idx
end
function buffer:read_avail()
   return to_uint32(self.write_idx - self.read_idx)
end
function buffer:is_full()
   return self:read_avail() == self.size
end
function buffer:write_avail()
   return self.size - self:read_avail()
end

function buffer:write_pos()
   return band(self.write_idx, self.size - 1)
end
function buffer:rewrite_pos(offset)
   return band(self.read_idx + offset, self.size - 1)
end
function buffer:read_pos()
   return band(self.read_idx, self.size - 1)
end

function buffer:advance_write(count)
   self.write_idx = self.write_idx + count
end
function buffer:advance_read(count)
   self.read_idx = self.read_idx + count
end

function buffer:write(bytes, count)
   if count > self:write_avail() then error('write xrun') end
   local pos = self:write_pos()
   local count1 = math.min(self.size - pos, count)
   ffi.copy(self.buf + pos, bytes, count1)
   ffi.copy(self.buf, bytes + count1, count - count1)
   self:advance_write(count)
end

function buffer:rewrite(offset, bytes, count)
   if offset + count > self:read_avail() then error('rewrite xrun') end
   local pos = self:rewrite_pos(offset)
   local count1 = math.min(self.size - pos, count)
   ffi.copy(self.buf + pos, bytes, count1)
   ffi.copy(self.buf, bytes + count1, count - count1)
end

function buffer:read(bytes, count)
   if count > self:read_avail() then error('read xrun') end
   local pos = self:read_pos()
   local count1 = math.min(self.size - pos, count)
   ffi.copy(bytes, self.buf + pos, count1)
   ffi.copy(bytes + count1, self.buf, count - count1)
   self:advance_read(count)
end

function buffer:drop(count)
   if count > self:read_avail() then error('read xrun') end
   self:advance_read(count)
end

function buffer:peek()
   local pos = self:read_pos()
   return self.buf + pos, math.min(self:read_avail(), self.size - pos)
end

buffer_t = ffi.metatype("buffer_t", buffer)

local function selftest()
   print('selftest: lib.buffer')
   local function assert_throws(f, ...)
      local success, ret = pcall(f, ...)
      assert(not success, "expected failure but got "..tostring(ret))
   end
   local function assert_avail(b, readable, writable)
      assert(b:read_avail() == readable)
      assert(b:write_avail() == writable)
   end
   local function write_str(b, str)
      local scratch = ffi.new('uint8_t[?]', #str)
      ffi.copy(scratch, str, #str)
      b:write(scratch, #str)
   end
   local function read_str(b, count)
      local scratch = ffi.new('uint8_t[?]', count)
      b:read(scratch, count)
      return ffi.string(scratch, count)
   end

   assert_throws(new, 10)
   local b = new(16)
   assert_avail(b, 0, 16)
   for i = 1,10 do
      local s = '0123456789'
      write_str(b, s)
      assert_avail(b, #s, 16-#s)
      assert(read_str(b, #s) == s)
      assert_avail(b, 0, 16)
   end

   local ptr, avail = b:peek()
   assert(avail == 0)
   write_str(b, "foo")
   local ptr, avail = b:peek()
   assert(avail > 0)

   -- Test wrap of indices.
   local s = "overflow"
   b.read_idx = to_uint32(3 - #s)
   b.write_idx = b.read_idx
   assert_avail(b, 0, 16)
   write_str(b, s)
   assert_avail(b, #s, 16-#s)
   assert(read_str(b, #s) == s)
   assert_avail(b, 0, 16)

   print('selftest: ok')
end

return {
    new = new,
    selftest = selftest
}

With luajit's ffi or https://github.com/jmckaskill/luaffi I get the following:

$ lua
Lua 5.1.5  Copyright (C) 1994-2012 Lua.org, PUC-Rio
> buffer = require 'buffer'; buffer.selftest()
selftest: lib.buffer
selftest: ok
> 

But with cffi the selftest() causes the interpreter to abort

$ lua
Lua 5.1.5  Copyright (C) 1994-2012 Lua.org, PUC-Rio
> buffer = require 'buffer'; buffer.selftest()
selftest: lib.buffer
free(): invalid size
Aborted
$

Segmentation fault when assigning a Lua callback to a C struct

Hello,

thank you for this great work :)

I am trying to adapt an existing LuaJIT+ffi project such that it could run with Lua as well using the cffi package. Doing so I am stuck with the following use case. When assigning a Lua callback to a C struct I get a segfault. Yet it works with LuaJIT. Below is a minimal example:

local ffi = jit and require('ffi') or require('cffi')

ffi.cdef([[
struct structure {
        void (*callback)(void);
};
]])

local structure = ffi.new('struct structure')
structure.callback = function () end

The last line gives a segfault on Debian using Lua 5.4+cffi. What could be the reason?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.