pcall(require, "luarocks.require") require "alien" require "alien.struct" local dll = alien.alientest do local f = dll._testfunc_i_bhilfd f:types("int", "byte", "short", "int", "long", "float", "double") local result = f(string.byte("x"), 1, 3, 4, 5, 6) assert(result == 139) end do local f = dll._testfunc_i_bhilfd f:types{ ret = "int", "byte", "short", "int", "long", "float", "double" } local result = f(string.byte("x"), 1, 3, 4, 5, 6) assert(result == 139) end do local f = dll._testfunc_i_bhilfd f:types{ "byte", "short", "int", "long", "float", "double" } local result = f(string.byte("x"), 1, 3, 4, 5, 6) assert(result == 139) end do local f = dll._testfunc_p_p f:types("pointer", "ref int") local result, copy = f(42) assert(type(result) == "userdata") assert(copy == 42) end do local f = dll._testfunc_callback_i_if f:types("int", "int", "callback") local args = {} local expected = {262144, 131072, 65536, 32768, 16384, 8192, 4096, 2048, 1024, 512, 256, 128, 64, 32, 16, 8, 4, 2, 1} local function callback(v) table.insert(args, v) end local cb = alien.callback(callback, "int", "int") f(2 ^ 18, cb) assert(#args == #expected) for i, v in ipairs(args) do assert(args[i] == expected[i]) end end do local f = dll._testfunc_callback_i_if f:types("int", "int", "callback") local function callback(value) return value end local cb = alien.callback(callback, "int", "int") local cb2 = alien.callback(callback, { ret = "int", "int" }) local cb3 = alien.callback(callback, { "int" }) local result = f(-10, cb) assert(result == -18) local result = f(-10, cb2) assert(result == -18) local result = f(-10, cb3) assert(result == -18) end do local integrate = dll.integrate integrate:types("double", "double", "double", "callback", "long") local function func(x) return x ^ 2 end local result = integrate(0, 1, alien.callback(func, "double", "double"), 10) local diff = math.abs(result - 1/3) assert(diff < 0.01) end do dll.tf_b:types("byte", "byte") assert(dll.tf_b(-126) == -42) end do dll.tf_bb:types("byte", "byte", "byte") assert(dll.tf_bb(0, -126) == -42) end do dll.tf_B:types("char", "char") assert(dll.tf_B(255) == 85) end do dll.tf_bB:types("char", "byte", "char") assert(dll.tf_bB(0, 255) == 85) end do dll.tf_h:types("short", "short") assert(dll.tf_h(-32766) == -10922) end do dll.tf_bh:types("short", "byte", "short") assert(dll.tf_bh(0, -32766) == -10922) end do dll.tf_i:types("int", "int") assert(dll.tf_i(-2147483646) == -715827882) end do dll.tf_bi:types("int", "byte", "int") assert(dll.tf_bi(0, -2147483646) == -715827882) end do dll.tf_l:types("long", "long") assert(dll.tf_l(-2147483646) == -715827882) end do dll.tf_bl:types("long", "byte", "long") assert(dll.tf_bl(0, -2147483646) == -715827882) end do dll.tf_f:types("float", "float") assert(dll.tf_f(-42) == -14) end do dll.tf_bf:types("float", "byte", "float") assert(dll.tf_bf(0, -42) == -14) end do dll.tf_d:types("double", "double") assert(dll.tf_d(-42) == -14) end do dll.tf_bd:types("double", "byte", "double") assert(dll.tf_bd(0, -42) == -14) end do dll.tv_i:types("void", "int") assert(dll.tv_i(42) == nil) assert(dll.tv_i(-42) == nil) end do local strchr = dll.my_strchr strchr:types("pointer", "string", "char") assert(alien.tostring(strchr("abcdefghi", string.byte("b"))) == "bcdefghi") assert(strchr("abcdefghi", string.byte("x")) == nil) end do local strtok = dll.my_strtok strtok:types("pointer", "string", "string") local buf = alien.buffer("a\nb\nc") local lb = "\n" assert(alien.tostring((strtok(buf, lb))) == "a") assert(alien.tostring((strtok(nil, lb))) == "b") assert(alien.tostring((strtok(nil, lb))) == "c") assert(alien.tostring((strtok(nil, lb))) == nil) end do local f = dll._testfunc_v f:types("void", "int", "int", "ref int") local r1, r2 = f(1, 2, 0) assert(r1 == nil) assert(r2 == 3) end do local f = dll._testfunc_i_bhilfd f:types("int", "byte", "short", "int", "long", "float", "double") local result = f(1, 2, 3, 4, 5, 6) assert(result == 21) local result = f(-1, -2, -3, -4, -5, -6) assert(result == -21) f:types("short", "byte", "short", "int", "long", "float", "double") local result = f(1, 2, 3, 4, 5, 6) assert(result == 21) local result = f(1, 2, 3, 0x10004, 5.0, 6.0) assert(result == 21) end do local f = dll._testfunc_f_bhilfd f:types("float", "byte", "short", "int", "long", "float", "double") local result = f(1, 2, 3, 4, 5.0, 6.0) assert(result == 21) local result = f(-1, -2, -3, -4, -5, -6) assert(result == -21) end do local f = dll._testfunc_d_bhilfd f:types("double", "byte", "short", "int", "long", "float", "double") local result = f(1, 2, 3, 4, 5.0, 6.0) assert(result == 21) local result = f(-1, -2, -3, -4, -5, -6) assert(result == -21) end do local f = dll._testfunc_p_p f:types("pointer", "string") local result = f("123") assert(alien.tostring(result) == "123") local result = f(nil) assert(result == nil) end do local f = dll.my_sqrt f:types("double", "double") assert(f(4) == 2) assert(f(2) == math.sqrt(2)) end do local function sort(a, b) return a - b end local compare = alien.callback(sort, "int", "ref char", "ref char") local qsort = dll.my_qsort qsort:types("void", "pointer", "int", "int", "callback") local chars = alien.buffer("spam, spam, and spam") qsort(chars, chars:len(), alien.sizeof("char"), compare) assert(chars:tostring() == " ,,aaaadmmmnpppsss") end do local funcs = alien.buffer(2 * alien.sizeof("callback")) local res = {} local function callback(a, b) table.insert(res, a + b) end local cb1 = alien.callback(callback, { "int", "int" }) local cb2 = alien.callback(callback, { abi = "stdcall", "int", "int" }) funcs:set(1, cb1, "callback") funcs:set(1 + alien.sizeof("callback"), cb2, "callback") local f = dll._testfunc_callfuncp f:types("int", "pointer") f(funcs) assert(#res == 2) assert(res[1] == 3) assert(res[2] == 7) end do local tag1 = alien.tag("alientest_tag1") assert(type(tag1) == "table") local tag2 = alien.tag("alientest_tag1") assert(tag1 == tag2) local tag3 = alien.tag("alientest_tag3") assert(tag1 ~= tag3) assert(type(tag3) == "table") end dll.my_malloc:types("pointer", "int") dll.my_free:types("void", "pointer") do local tag = alien.tag("alientest_tag") local ptr = dll.my_malloc(4) local obj = alien.wrap("alientest_tag", 1, 2, ptr, 10) assert(getmetatable(obj) == tag) local x, y, o, z = alien.unwrap("alientest_tag", obj) assert(x == 1 and y == 2 and o == ptr and z == 10) alien.rewrap("alientest_tag", obj, 3, 4, nil, 5) local x, y, o, z = alien.unwrap("alientest_tag", obj) assert(x == 3 and y == 4 and o == nil and z == 5) dll.my_free(ptr) end local types = { "char", "short", "int", "long" } for _, t in ipairs(types) do local buf = alien.buffer(alien.sizeof(t)) local ptr = buf:topointer() buf:set(1, 5, t) assert(alien["to" .. t](ptr) == 5) end local types = { "float", "double"} for _, t in ipairs(types) do local buf = alien.buffer(alien.sizeof(t)) local ptr = buf:topointer() buf:set(1, 2.5, t) assert(alien["to" .. t](ptr) == 2.5) end local types = { "char", "short", "int", "long" } for _, t in ipairs(types) do local buf = alien.buffer(alien.sizeof(t) * 4) local ptr = buf:topointer() for i = 1, alien.sizeof(t) * 4, alien.sizeof(t) do buf:set(i, i * 2, t) end local vals = { alien["to" .. t](ptr, 4) } assert(#vals == 4) for i = 1, 4 do assert(vals[i] == (((i - 1) * alien.sizeof(t)) + 1) * 2) end end local types = { "float", "double"} for _, t in ipairs(types) do local buf = alien.buffer(alien.sizeof(t) * 4) local ptr = buf:topointer() for i = 1, alien.sizeof(t) * 4, alien.sizeof(t) do buf:set(i, i * 2 + 0.5, t) end local vals = { alien["to" .. t](ptr, 4) } assert(#vals == 4) for i = 1, 4 do assert(vals[i] == (((i - 1) * alien.sizeof(t)) + 1) * 2 + 0.5) end end do local function callback(a, b) return a + b end local cb1 = alien.callback(callback, { "int", "int" }) local cb2 = alien.callback(callback, { abi = "stdcall", "int", "int" }) assert(cb1(2, 3) == 5) assert(cb2(3, 4) == 7) local f = dll._testfunc_p_p f:types("pointer", "callback") local cb3 = alien.funcptr(f(cb1)) cb3:types{ "int", "int" } assert(cb3(2, 3) == 5) end do local function sort(a, b) return a - b end local compare = alien.callback(sort, "int", "ref char", "ref char") local qsort = dll.my_qsort qsort:types("void", "pointer", "int", "int", "callback") local str = "spam, spam, and spam" local chars = alien.array("char", #str, alien.buffer(str)) qsort(chars.buffer, chars.length, chars.size, compare) assert(tostring(chars.buffer) == " ,,aaaadmmmnpppsss") end local types = { "char", "int", "double" } for _, t in ipairs(types) do local function sort(a, b) return a - b end local compare = alien.callback(sort, "int", "ref " .. t, "ref " .. t) local qsort = dll.my_qsort qsort:types("void", "pointer", "int", "int", "callback") local nums = alien.array(t, { 4, 5, 3, 2, 6, 1 }) qsort(nums.buffer, nums.length, nums.size, compare) for i = 1, 6 do assert(nums[i] == i) end end do local function sort(a, b) a = alien.buffer(a):get(1, "string") b = alien.buffer(b):get(1, "string") if a == b then return 0 elseif a < b then return -1 else return 1 end end local compare = alien.callback(sort, "int", "pointer", "pointer") local qsort = dll.my_qsort qsort:types("void", "pointer", "int", "int", "callback") local strs = alien.array("string", { "Red", "Yellow", "Blue" }) qsort(strs.buffer, strs.length, strs.size, compare) assert(strs[1] == "Blue") assert(strs[2] == "Red") assert(strs[3] == "Yellow") end local types = { "char", "short", "int", "long", "float", "double" } for _, t in ipairs(types) do local arr = alien.array(t, 4) assert(arr.length == 4) assert(arr.size == alien.sizeof(t)) assert(arr.type == t) for i = 1, arr.length do arr[i] = i end for i = 1, arr.length do assert(arr[i] == i) end local tab = {} for i, v in arr:ipairs() do tab[i] = v end assert(#tab == 4) for i = 1, 4 do assert(tab[i] == i) end assert(not pcall(function () return arr[0] end)) assert(not pcall(function () return arr[5] end)) end