2016-04-19 11 views
0

Ich arbeite an dem Erstellen einer Lua-Bindung zu einem anderen C++ - Projekt. Nach einigen Untersuchungen scheint LuaJIT FFI die beste Wahl zu sein, um dieses Ziel zu erreichen. Ich profitiere wirklich von dem Lua-User-Mail-Listen-Archiv [1] und einer anderen verwandten Folie [2]. Eigentlich ist hier eine Hello World-Probe gemacht [3] und jegliche Verbesserungsvorschläge sind willkommen.Wie verwendet man shared_ptr in LuaJIT FFI/C++ - Bindung?

Derzeit versuche ich shared_ptr zu diesem Beispiel einzuführen, so dass ich nicht über Garbage Collection Problem kümmern muss. Aber aufgrund meiner schlechten Erfahrung sowohl bei Lua als auch bei LuaJIT gibt das Lua-Skript immer Segmentation fault zurück und ich weiß nicht, wie ich das debuggen soll. Die Code-Snippets sind wie folgt aufgelistet und wünschen Ihnen, dass talentierte Leute mir praktische Ratschläge geben können.

Das ist hello.cpp und der Befehl, den ich verwende, um die Bibliothek zu erstellen, ist g++ -std=c++11 -shared -fPIC -o libhello.so hello.cpp.

#include<memory> 
using namespace std; 

class Hello { 
    public: 
     const char* World() 
     { 
      return "Hello World!\n"; 
     } 
}; 

typedef shared_ptr<Hello> pHello; 

extern "C" { 
    pHello Hello_new(){ 
     return pHello(); 
    } 

    const char* Hello_World(pHello self){ 
     return self->World(); 
    } 
} 

Dies ist der hello.lua mit luajit hello.lua Befehl ausgeführt wird.

ffi = require('ffi') 
ffi.cdef[[ 
    typedef struct pHello pHello; 

    pHello Hello_new(); 
    const char* Hello_World(pHello); 
]] 
hello = ffi.load('hello') 

hello_index = { 
    World = hello.Hello_World 
} 
hello_mt = ffi.metatype('pHello', { 
    __index = hello_index 
}) 
Hello = hello.Hello_new 

hello = Hello() 
io.write(ffi.string(hello:World())) 
+0

Ich weiß nicht, wie LuaJIT sogar Ihr cdef akzeptiert; 'struct pHello' hat keine Definition, daher kann LuaJIT nicht wissen, wie groß es ist und wieviele Bytes' Hello_new' zurückgibt. Stellen Sie auf keinen Fall ein 'shared_ptr' in einer C-API direkt zur Verfügung - es gibt keine gute Möglichkeit, es in C zu verwenden. –

Antwort

1

Dinge nicht funktionieren, wie Sie sie tun erwarten.

Zunächst einmal ist Ihr C++ - Code fehlerhaft: Der Aufruf return pHello() gibt eine leere shared_ptr ohne verwaltetes Objekt (sagen: Nullzeiger) zurück. Wenn Sie ein neues Objekt erstellen möchten, rufen Sie return std::make_shared<Hello>().

Abgesehen davon hilft die Verwendung einer shared_ptr Ihnen nicht in Bezug auf Garbage Collection. Die Referenzzählung, die vom intelligenten Zeiger ausgeführt wird, beruht auf dem aufgerufenen Destruktor, einem C++ - Mechanismus. Da die FFI-Bibliothek mit C-Code interagiert, wird dies nicht passieren, egal wie Sie es einbetten, um es an LuaJIT zu übergeben (Ihr Compiler hätte Sie vor der Verwendung von `extern" C zusammen mit einem klassenbasierten Rückgabetyp warnen müssen) .

Der Standard Weg (wenn Sie sich auf Garbage Collection verlassen wollen) ist, lassen Sie die __gc Metamethod eine Funktion aufrufen, die delete auf der C++ Seite tun. Dies ist der C-Weg: Sie haben in Ihrem Funktionsaufruf eine Ressource zugewiesen, Sie sind dafür verantwortlich, diese anschließend freizugeben.

Ich würde empfehlen, einen einfachen Wrapper um Ihre Klasse zu schreiben, vielleicht mit reinem Lua API zuerst, um die Grundlagen zu lernen. Wenn Sie Objekte freigegeben haben und die Referenz nicht selbst zählen möchten, gehen Sie später zum Umbruch shared_ptr über.

+0

Vielen Dank für Ihre Erklärung. –

Verwandte Themen