Giter Site home page Giter Site logo

luaffi's Introduction

About

This is a library for calling C function and manipulating C types from lua. It is designed to be interface compatible with the FFI library in luajit (see http://luajit.org/ext_ffi.html). It can parse C function declarations and struct definitions that have been directly copied out of C header files and into lua source as a string.

License

Copyright (c) 2011 James R. McKaskill. MIT same as Lua 5.1. See full license text in ffi.h.

Source

https://github.com/jmckaskill/luaffi

Platforms

Currently supported:

  • windows x86/x64
  • linux x86/x64
  • windows CE ARM little endian (ARMv4+)
  • OSX x86/x64

Currently only dll builds are supported (ie no static).

Runs with both Lua 5.1 and Lua 5.2 beta.

Build

On windows use msvcbuild.bat in a visual studio cmd prompt. Available targets are:

  • nothing or release: default release build
  • debug: debug build
  • test: build and run the test debug build
  • test-release: build and run the test release build
  • clean: cleanup object files

Edit msvcbuild.bat if your lua exe, lib, lua include path, or lua dll name differ from c:\Lua5.1 and lua5.1.dll.

The build script does not build for CE as this is non-trivial and very dependent on which CE profile (or even a custom one). Instead to build on CE, add generate_call_h.bat as a pre-build event and then build *.c with UNDER_CE defined plus whatever defines windows.h requires.

On posix use make. Available targets are:

  • nothing or all: default release build
  • debug: debug build
  • test: build and run the test build
  • clean: cleanup object files
  • macosx: release build for Mac OSX

Edit the Makefile if your lua exe differs from lua5.1 or if you can't get the include and lib arguments from pkg-config.

Known Issues

  • Has not been bullet proof tested
  • Casting is different from luajit. For the moment this follows C++
    • ffi.cast is equivalent to a C cast in C++ (T t = (T) f)
    • ffi.new and ctype() is equivalent to an implicit cast in C++ (T t = f)
      • since this follows C++ semantics void* does not cast to T* (an explicit cast using ffi.cast is required)
  • Comparing a ctype pointer to nil doesn't work the same as luajit. This is unfixable with the current metamethod semantics. Instead use ffi.C.NULL
  • Constant expressions can't handle non integer intermediate values (eg offsetof won't work because it manipulates pointers)
  • Not all metamethods work with lua 5.1 (eg char* + number). This is due to the way metamethods are looked up with mixed types in Lua 5.1. If you need this upgrade to Lua 5.2 or use boxed numbers (uint64_t and uintptr_t).
  • All bitfields are treated as unsigned (does anyone even use signed bitfields?). Note that "int s:8" is unsigned on unix x86/x64, but signed on windows.

Todo

See Github issues for the most up to date list.

  • Fix arm support - broken since the callback refactor
  • Vectors
  • C++ reference types
  • Subtracting one pointer from another
  • Variable sized members in unions (is this needed?)

How it works

Types are represented by a struct ctype structure and an associated user value table. The table is shared between all related types for structs, unions, and functions. It's members have the types of struct members, function argument types, etc. The struct ctype structure then contains the modifications from the base type (eg number of pointers, array size, etc).

Types are pushed into lua as a userdata containing the struct ctype with a user value (or fenv in 5.1) set to the shared type table.

Boxed cdata types are pushed into lua as a userdata containing the struct cdata structure (which contains the struct ctype of the data as its header) followed by the boxed data.

The functions in ffi.c provide the cdata and ctype metatables and ffi.* functions which manipulate these two types.

C functions (and function pointers) are pushed into lua as a lua c function with the function pointer cdata as the first upvalue. The actual code is JITed using dynasm (see call_x86.dasc). The JITed code does the following in order:

  1. Calls the needed unpack functions in ffi.c placing each argument on the HW stack
  2. Updates errno
  3. Performs the c call
  4. Retrieves errno
  5. Pushes the result back into lua from the HW register or stack

luaffi's People

Contributors

fjolnir avatar jjensen avatar jmckaskill avatar justincormack 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  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

luaffi's Issues

2 arg form of ffi.copy not supported

This should work:

local ffi = require "ffi"

s = "test"

c = ffi.new("char[40]")

ffi.copy(c, s)

for copying Lua strings, the 2 argument form of ffi.copy, but we get


lua: tmp.lua:7: bad argument #3 to 'copy' (number expected, got table)
stack traceback:
    [C]: in function 'copy'
    tmp.lua:7: in main chunk
    [C]: ?

msvcbuild.bat LUA_EXE quoting

msvcbuild.bat is inconsistent in it's quoting;

@set LUA_INCLUDE=C:\Program Files (x86)\Lua\5.1\include
@set LUA_LIB=C:\Program Files (x86)\Lua\5.1\lib\lua5.1.lib
@set LUA_EXE="C:\Program Files (x86)\Lua\5.1\lua.exe"
@set LUA_DLL=C:\Program Files (x86)\Lua\5.1\lua5.1.dll

LUA_EXE needs quotes if it contains a space; the others don't work with quotes.

metatype initialization issue

this code

local ffi = require "ffi"

local fd = ffi.metatype("struct {int fileno;}", {})

local test = fd(2);

print(test.fileno)

Works fine in luajit, and prints 2.

In luaffi I get

lua: unable to convert argument 2 from lua<number> to cdata<struct 2>
stack traceback:
    [C]: in function 'fd'
    tmp.lua:5: in main chunk
    [C]: ?

Unfortunately I use this idiom a lot as thats the only sane way to have garbage collection on file descriptors, by adding __gc method to fd. There would be a fair amount of workaround to avoid this usage, by explicitly initializing ie this which does work:

local ffi = require "ffi"

local fd = ffi.metatype("struct {int fileno;}", {})

local test = fd();

test.fileno = 2

print(test.fileno)

Convert string to unsigned char array

We can't convert a Lua string to an array of unsigned characters (or other varieties of 8-bit unsigned types like uint8_t).

local ffi = require "ffi"
ffi.cdef[[
int strncmp(const char *s1, const unsigned char *s2, size_t n);
]]
print (ffi.C.strncmp("two", "three", 3))

returns:

lua: unable to convert argument 2 from lua<string> to cdata<const unsigned char*>
stack traceback:
        [C]: in function 'strncmp'
        string_ffi.lua:7: in main chunk
        [C]: in ?

This runs with LuaJIT2, but not with luaffi. I initially stumbled upon this problem when going through the FFI tutorial.

Add vector types

Vector types, declared with the GCC mode or vector_size attribute.

__attribute__((packed)) should pack its members

With this declaration:

typedef union epoll_data
{
  void *ptr;
  int fd;
  uint32_t u32;
  uint64_t u64;
} epoll_data_t;
struct epoll_event
{
  uint32_t events;
  epoll_data_t data;
} __attribute__ ((__packed__));

Running this:

local __events = ffi.new ( "struct epoll_event[1]" )
__events[0].events = 8193
__events[0].data.fd = fd.fd
for i=0,2 do
    print("A",i,ffi.cast("int*",__events[0])[i])
end

Will print:

A   0   8193
A   1   0
A   2   5

As opposed to the expected

A   0   8193
A   1   5
A   2   0

casting between numbers and pointers

in luajit the ffi can cast numbers to and from pointers.

eg S.cast("char *", 1) gives a pointer to memory location 1
and I can use
ffi.cast("long", ret) == -1
to test the return value from mmap.

I can't work out how to do either of those with luaffi, so I can't get mmap to work for ljsyscall.

segfault

running lua test.lua on the head version of ljsyscall now gives

lua: ffi.c:708: get_member: Assertion `ct->is_variable_struct && ct->variable_size_known && mt->is_array' failed.
and segfaults

Will make a reduced test case, its after the recvmsg call, passing credentials, not the simplest interface...

tonumber no longer works with 2 args

you override tonumber but it no longer works in the case where there is a second argument... eg tonumber('100', 8) returns 100 not 64 after including ffi.

Linux 32 bit make error

In Linux Mint 14 Mate 32 bit I get an error:

make posix
lua dynasm/dynasm.lua -LN -o call_x86.h call_x86.dasc
lua dynasm/dynasm.lua -D X64 -LN -o call_x64.h call_x86.dasc
lua dynasm/dynasm.lua -D X64 -D X64WIN -LN -o call_x64win.h call_x86.dasc
cc -fPIC -g -Wall -Werror pkg-config --cflags lua5.1 2>/dev/null || pkg-config --cflags lua -fvisibility=hidden -Wno-unused-function --std=gnu99 -o ffi.o -c ffi.c
ffi.c: In function ‘check_pointer’:
ffi.c:469:20: error: cast to pointer from integer of different size [-Werror=int-to-pointer-cast]
cc1: all warnings being treated as errors
make: *** [ffi.o] Error 1

Automatic casting of lua file handles,

Quoting Mike Pall:

I've added conversion of an io.* file handle to a FILE *. Actually
it converts to a void * because I don't want to expose a standard
'FILE' C type. But this doesn't matter as it converts to a FILE *
argument of a C function.

The changes have been pushed to git HEAD. Provided you add the
required C function declarations, you can do this now:

 ffi.C.fputs("test\n", io.stderr)
 ffi.C.fprintf(io.stderr, "Hello %s\n", "world")

 if ffi.abi("win") then
   print(ffi.C._fileno(io.stderr))    --> 2
 else
   print(ffi.C.fileno(io.stderr))     --> 2
 end

Ditto for any file handle you get from io.open() or io.popen().

sigaction

Getting confused with a struct and function having the same name?

> S.sigaction( S.SIGINT, function(sig) g_terminated = true end )
lua: unable to convert argument 8 from lua<table> to cdata<uint64_t>
stack traceback:
   [C]: in function 'sigaction_t'
   ./io/syscall.lua:2880: in function 'sigaction'

Structs as call argument types/return types

Need support in both compile_function arg/return and compile_callback arg/return. Need to double check ABI, but return should be similar to complex double on x86 with a hidden first param. Arg ABI is to unpack?

Indexing a complex number

From FFI semantics (http://luajit.org/ext_ffi_semantics.html):
a complex number can be indexed either by a cdata number or a Lua number with the values 0 or 1, or by the strings "re" or "im". A read access loads the real part ([0], .re) or the imaginary part ([1], .im) part of a complex number and converts it to a Lua number. The sub-parts of a complex number are immutable — assigning to an index of a complex number raises an error. Accessing out-of-bound indexes returns unspecified results, but is guaranteed not to trigger memory access violations.

Windows build failure (VS2010)

U:\Programming\luaffi>msvcbuild.bat

U:\Programming\luaffi>"C:\Program Files (x86)\Lua\5.1\lua.exe" dynasm\dynasm.lua
-LNE -D X32WIN -o call_x86.h call_x86.dasc

U:\Programming\luaffi>"C:\Program Files (x86)\Lua\5.1\lua.exe" dynasm\dynasm.lua
-LNE -D X64 -o call_x64.h call_x86.dasc

U:\Programming\luaffi>"C:\Program Files (x86)\Lua\5.1\lua.exe" dynasm\dynasm.lua
-LNE -D X64 -D X64WIN -o call_x64win.h call_x86.dasc

U:\Programming\luaffi>"C:\Program Files (x86)\Lua\5.1\lua.exe" dynasm\dynasm.lua
-LNE -o call_arm.h call_arm.dasc

U:\Programming\luaffi>cl.exe /nologo /c /MD /Ox /W3 /Zi /WX /D_CRT_SECURE_NO_DEP
RECATE /DLUA_FFI_BUILD_AS_DLL /I"msvc" /I"." /I"C:\Program Files (x86)\Lua\5.1\i
nclude" /DLUA_DLL_NAME="C:\Program Files (x86)\Lua\5.1\lua5.1.dll" call.c ctype.
c ffi.c parser.c
call.c
ctype.c
ffi.c
ffi.c(1882) : error C2220: warning treated as error - no 'object' file generated

ffi.c(1882) : warning C4129: 'P' : unrecognized character escape sequence
ffi.c(1882) : warning C4129: 'L' : unrecognized character escape sequence
ffi.c(1882) : warning C4129: 'l' : unrecognized character escape sequence
parser.c
Generating Code...

U:\Programming\luaffi>link.exe /nologo /debug /DLL /OUT:ffi.dll "C:\Program File
s (x86)\Lua\5.1\lib\lua5.1.lib" *.obj
call.obj : error LNK2019: unresolved external symbol _unpack_varargs_int referen
ced in function _reserve_code
call.obj : error LNK2019: unresolved external symbol _unpack_varargs_float refer
enced in function _reserve_code
call.obj : error LNK2019: unresolved external symbol _unpack_varargs_reg referen
ced in function _reserve_code
call.obj : error LNK2019: unresolved external symbol _unpack_varargs_stack_skip
referenced in function _reserve_code
call.obj : error LNK2019: unresolved external symbol _unpack_varargs_stack refer
enced in function _reserve_code
call.obj : error LNK2019: unresolved external symbol _to_typed_function referenc
ed in function _reserve_code
call.obj : error LNK2019: unresolved external symbol _to_typed_pointer reference
d in function _reserve_code
call.obj : error LNK2019: unresolved external symbol _to_enum referenced in func
tion _reserve_code
call.obj : error LNK2019: unresolved external symbol _to_uintptr referenced in f
unction _reserve_code
call.obj : error LNK2019: unresolved external symbol _to_uint32 referenced in fu
nction _reserve_code
call.obj : error LNK2019: unresolved external symbol _to_int32 referenced in fun
ction _reserve_code
call.obj : error LNK2019: unresolved external symbol _to_int64 referenced in fun
ction _reserve_code
call.obj : error LNK2019: unresolved external symbol _to_uint64 referenced in fu
nction _reserve_code
call.obj : error LNK2019: unresolved external symbol _to_float referenced in fun
ction _reserve_code
call.obj : error LNK2019: unresolved external symbol _to_double referenced in fu
nction _reserve_code
ffi.dll : fatal error LNK1120: 15 unresolved externals

U:\Programming\luaffi>if exist ffi.dll.manifest mt.exe /nologo -manifest ffi.dll
.manifest -outputresource:"ffi.dll;2"

U:\Programming\luaffi>cl.exe /nologo /c /MD /Ox /W3 /Zi /WX /D_CRT_SECURE_NO_DEP
RECATE /DLUA_FFI_BUILD_AS_DLL /I"msvc" /Gd test.c /Fo"test_cdecl.obj"
test.c

U:\Programming\luaffi>cl.exe /nologo /c /MD /Ox /W3 /Zi /WX /D_CRT_SECURE_NO_DEP
RECATE /DLUA_FFI_BUILD_AS_DLL /I"msvc" /Gz test.c /Fo"test_stdcall.obj"
test.c

U:\Programming\luaffi>cl.exe /nologo /c /MD /Ox /W3 /Zi /WX /D_CRT_SECURE_NO_DEP
RECATE /DLUA_FFI_BUILD_AS_DLL /I"msvc" /Gr test.c /Fo"test_fastcall.obj"
test.c

U:\Programming\luaffi>link.exe /nologo /debug /DLL /OUT:test_cdecl.dll test_cdec
l.obj
LINK : test_cdecl.dll not found or not built by the last incremental link; perfo
rming full link
Creating library test_cdecl.lib and object test_cdecl.exp

U:\Programming\luaffi>link.exe /nologo /debug /DLL /OUT:test_stdcall.dll test_st
dcall.obj
LINK : test_stdcall.dll not found or not built by the last incremental link; per
forming full link
Creating library test_stdcall.lib and object test_stdcall.exp

U:\Programming\luaffi>link.exe /nologo /debug /DLL /OUT:test_fastcall.dll test_f
astcall.obj
LINK : test_fastcall.dll not found or not built by the last incremental link; pe
rforming full link
Creating library test_fastcall.lib and object test_fastcall.exp

U:\Programming\luaffi>if exist test_cdecl.dll.manifest mt.exe /nologo -manifest
test_cdecl.dll.manifest -outputresource:"test_cdecl.dll;2"

U:\Programming\luaffi>if exist test_stdcall.dll.manifest mt.exe /nologo -manifes
t test_stdcall.dll.manifest -outputresource:"test_stdcall.dll;2"

U:\Programming\luaffi>if exist test_fastcall.dll.manifest mt.exe /nologo -manife
st test_fastcall.dll.manifest -outputresource:"test_fastcall.dll;2"

U:\Programming\luaffi>del *.obj *.manifest

ffi.cdef doesn't understand/skip __attribute__

Unlike the luajit ffi; ffi.cdef doesn't understand or skip __attribute__

eg:
ffi = require"ffi" ffi.cdef [[ typedef int ALenum; __attribute__((dllimport)) void __attribute__((__cdecl__)) alEnable( ALenum capability ); ]]
error: unknown type __attribute__ on line 2

2 arg for of ffi.fill not supported

ffi.fill with 2 args does a zero fill, but gives

test: ./syscall.lua:3833: bad argument #3 to 'fill' (number expected, got table)
stack traceback:
    [C]: in function 'fill'
    ./syscall.lua:3833: in function '?'
    test.lua:647: in main chunk
    [C]: ?

Casting and calling a vararg function

I noticed that casting didn't work how it does in luajit.
When calling a vararg function, the casts don't seem to do the correct thing.
Consider a short example that sets a file descriptor as non-blocking:

local bit = require "bit"
local ffi = require "ffi"
ffi.cdef[[extern int fcntl (int __fd, int __cmd, ...);]]

F_GETFL = 3
F_SETFL = 4
O_NONBLOCK = tonumber("04000",8)

local fd = 0
local flags = ffi.C.fcntl(fd,F_GETFL)
flags = bit.bor ( flags , O_NONBLOCK )
ffi.C.fcntl ( fd , F_SETFL , ffi.cast("int",flags) )

assert( ffi.C.fcntl(fd,F_GETFL) == flags )

Looking via strace, this is actually doing:

fcntl(0, F_GETFL)                       = 0x8402 (flags O_RDWR|O_APPEND|O_LARGEFILE)
fcntl(0, F_SETFL, O_RDWR|O_EXCL|O_NOCTTY|O_TRUNC|O_APPEND|O_NONBLOCK|O_LARGEFILE|0x20) = 0
fcntl(0, F_GETFL)                       = 0x8c02 (flags O_RDWR|O_APPEND|O_NONBLOCK|O_LARGEFILE)

ffi.c:164:3: error: variable ‘imag’ set but not used [-Werror=unused-but-set-variable]

The problem appears to be your TO_NUMBER macro along with using Werror

Compile log:

$ make
if [ uname = "Darwin" ]; then make macosx; else make posix; fi
make[1]: Entering directory /home/daurnimator/src/luaffi' ../lua-5.2.0/src/lua dynasm/dynasm.lua -LN -o call_x86.h call_x86.dasc ../lua-5.2.0/src/lua dynasm/dynasm.lua -D X64 -LN -o call_x64.h call_x86.dasc ../lua-5.2.0/src/lua dynasm/dynasm.lua -D X64 -D X64WIN -LN -o call_x64win.h call_x86.dasc cc -O2 -fPIC -g -Wall -Werror -fvisibility=hidden -Wno-unused-function --std=gnu99 -o ffi.o -c ffi.c ffi.c: In function ‘check_int32’: ffi.c:164:3: error: variable ‘imag’ set but not used [-Werror=unused-but-set-variable] ffi.c: In function ‘check_uint32’: ffi.c:167:3: error: variable ‘imag’ set but not used [-Werror=unused-but-set-variable] ffi.c: In function ‘check_int64’: ffi.c:170:3: error: variable ‘imag’ set but not used [-Werror=unused-but-set-variable] ffi.c: In function ‘check_uint64’: ffi.c:173:3: error: variable ‘imag’ set but not used [-Werror=unused-but-set-variable] ffi.c: In function ‘check_double’: ffi.c:176:3: error: variable ‘imag’ set but not used [-Werror=unused-but-set-variable] ffi.c: In function ‘check_float’: ffi.c:179:3: error: variable ‘imag’ set but not used [-Werror=unused-but-set-variable] ffi.c: In function ‘check_uintptr’: ffi.c:182:3: error: variable ‘imag’ set but not used [-Werror=unused-but-set-variable] cc1: all warnings being treated as errors make[1]: *** [ffi.o] Error 1 make[1]: Leaving directory/home/daurnimator/src/luaffi'
make: *** [all] Error 2

Crash in copy_submembers()

Using the ffi call below with latest luaffi, the following crashes in copy_submembers() on this line:

        ct = *(const struct ctype*) lua_touserdata(L, -1);

Running under LuaJIT yields a proper result and no crash.

Thanks for the help!

-Josh

ffi = require 'ffi'

ffi.cdef [[
typedef struct _SYSTEM_INFO {
  union {
    unsigned long  dwOemId;
    struct {
      unsigned short wProcessorArchitecture;
      unsigned short wReserved;
    } ;
  } ;
  unsigned long     dwPageSize;
  void*    lpMinimumApplicationAddress;
  void*    lpMaximumApplicationAddress;
  unsigned long dwActiveProcessorMask;
  unsigned long     dwNumberOfProcessors;
  unsigned long     dwProcessorType;
  unsigned long     dwAllocationGranularity;
  unsigned short      wProcessorLevel;
  unsigned short      wProcessorRevision;
} SYSTEM_INFO;

void GetSystemInfo(
  SYSTEM_INFO* lpSystemInfo
);
]]

local info = ffi.new("SYSTEM_INFO")
ffi.C.GetSystemInfo(info)

print(info.dwNumberOfProcessors)

unable to convert argument ...

I'm having trouble reducing to a small test case, but things work fine under luajit.

When running the code:

local mask = ffi.new ( "sigset_t[1]" )
ffi.C.sigemptyset ( mask )

I get the error: unable to convert argument 1 from cdata<struct 61[1]> to cdata<struct 26*>

sigemptyset is declared via:

typedef struct
  {
    unsigned long int __val[(1024 / (8 * sizeof (unsigned long int)))];
  } __sigset_t;
extern int sigemptyset (sigset_t *__set) __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__nonnull__ (1)));

though the trailing attributes don't seem to matter

Is ARM support still broken?

Just wanted to see where this project was left off. Is the ARM support still broken? I'd like to use this on an i.MX6 class device (ARM Cortex A9). Is there any reason this would not work? How extensively has it been tested (e.g. what is known to be broken)?

Any feedback would be appreciated.

ffi.new() - add variable number of arguments for Initializers

According to the rules for initializers:

http://luajit.org/ext_ffi_semantics.html#init

"Aggregate types (arrays and structs) accept either a single table initializer or a flat list of initializers." So we should be able to initialize a C array with a table:

list = ffi.new("int[3]", {10, 20, 30})

or by giving all the arguments to the ffi.new() call itself:

list = ffi.new("int[3]", 10, 20, 30)

However, the latter does not work, and you get an error:

unable to convert argument 2 from lua<number> to cdata<int[3]>

I can't seem to set enum values

Setting enums in a struct doesn't seem to work;
Same error if you do it in the constructor; or afterwards.

A test case:

ffi = require"ffi"

ffi.cdef [[
    typedef enum {
    foo,
    } an_enum;

    typedef struct {
    an_enum x;
    } a_struct;
]]

local new = ffi.typeof ( "a_struct" )
new(ffi.C.foo)

ERROR:
lua: unable to convert argument 2 from lua to cdata<struct 2>

Global constants don't work

As far as I can tell, cdef only lets you define functions or types. Meaning that code like the following does not work(Does work fine in LuaJIT however)

ffi.cdef[[
// http://clang.llvm.org/docs/Block-ABI-Apple.txt
struct __block_descriptor_1 {
    unsigned long int reserved; // NULL
    unsigned long int size; // sizeof(struct __block_literal_1)
};

struct __block_literal_1 {
    struct __block_literal_1 *isa;
    int flags;
    int reserved;
    void *invoke;
    struct __block_descriptor_1 *descriptor;
};

const struct __block_literal_1 *_NSConcreteGlobalBlock; // <-- problem line
]]

Fails with: unexpected type in root on line 15

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.