LoginSignup
0
0

More than 1 year has passed since last update.

luajitでnewしたメモリのポインタはlua_topointerで受け取る

Posted at

 
この記事はアドカレに参加しています。

luajitでnewしたメモリのポインタはlua_topointerで受け取る

小ネタとも言えないような小ネタです。

obj.getpixeldataしたやつの場合

lua側でobj.getpixeldataしたメモリの場合、dll側でポインタを受け取る際には、

char* data = reinterpret_cast<char*>(lua_touserdata(L, 1));

…のようにします。これは、obj.getpixeldataがライトユーザーデータ(たぶん)を返す関数であり、ライトユーザーデーターをdllで受けとるにはlua_touserdata関数を使用する必要があるからです。

ffi.newしたものはどうするのか…?

さて、luajitでnewしたとします。

local a=ffi.new("int[10]",{})

そして、dllの関数に引数として渡したとします。

d.func0(a)

このときにdll側でlua_touserdata関数を使用していると、NULLが返されます。
newしたメモリはライトユーザーデーターではないからです。

そこで、lua_topointer関数を使用します。

char* data = reinterpret_cast<char*>(const_cast<void*>(lua_topointer(L, 1)));

こうすることで、dll内でnewしたメモリにアクセスすることができます。

サンプル

<?--サイズ60のテキストボックスに
local ffi=require("ffi")
local a=ffi.new("int[10]",{})

for i=0,9 do
obj.load(a[i])
obj.draw(-50,50*i+50)
end

local d=require("test_dll")
d.func0(a,0)
obj.load(string.format("%s",a))
obj.draw()

for i=0,9 do
obj.load(a[i])
obj.draw(50,50*i+50)
end
?>

#include <lua.hpp>
#include "windows.h"

int func0(lua_State* L) {
    char t[100];
    ZeroMemory(t, 100);

    int* data = reinterpret_cast<int*>(const_cast<void*>(lua_topointer(L, 1)));
    if (lua_tointeger(L, 2) == 1) {
        wsprintfA(t, "%p", data);
        MessageBoxA(NULL, t, "test.exe", MB_OKCANCEL);
    }

    for (int i = 0; i < 10; i++) {
        data[i] = i;
    }

    return 0;
}

static luaL_Reg functions[] = {
    {"func0",func0},
    {nullptr,nullptr}
};

extern "C" {
    __declspec(dllexport) int luaopen_test_dll(lua_State* L) {
        luaL_register(L, "test_dll", functions);
        return 1;
    }
}

おわりに

けっこう詰まっていたことだったので、記事にして残しておきます。
これだけのことで数日潰したんですが、長文読みたくなくて避けていたリファレンスマニュアルに普通に書かれていたりするので、マニュアル熟読大事ですね。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0