2016-04-19 1 views
0

Je travaille sur la création d'une liaison Lua à un autre projet C++. Après une enquête, LuaJIT FFI semble être le meilleur choix pour atteindre cet objectif. Je profite vraiment de l'archive de la liste de diffusion de lua-user [1] et d'une autre diapositive connexe [2]. En fait, un échantillon Hello World est fait ici [3] et toutes les suggestions d'amélioration sont les bienvenues.Comment utiliser shared_ptr dans une liaison LuaJIT FFI/C++?

Actuellement j'essaye d'introduire shared_ptr à cet échantillon de sorte que je n'aurai pas besoin de m'inquiéter au sujet de la collection de garbage. Mais en raison de ma mauvaise expérience sur Lua et LuaJIT, le script Lua renvoie toujours Segmentation fault et je ne sais même pas comment déboguer cela. Les extraits de code sont listés comme suit et vous souhaitent des gars talentueux peuvent me donner quelques conseils pratiques.

Ceci est hello.cpp et la commande que j'utilise pour créer la bibliothèque est 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(); 
    } 
} 

C'est le hello.lua avec la commande en cours d'exécution luajit hello.lua.

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

Je ne sais pas comment LuaJIT accepte même votre cdef; 'struct pHello' n'a pas de définition, donc LuaJIT ne peut pas savoir à quel point il est grand et combien d'octets' Hello_new' retourne. Dans tous les cas, n'exposez pas directement 'shared_ptr' dans une API C - il n'y a pas de bon moyen de le faire fonctionner en C. –

Répondre

1

Les choses ne fonctionnent pas comme vous attendez d'eux.

Tout d'abord, votre code C++ est erronée: L'appel return pHello() retourne un shared_ptr vide sans objet géré (par exemple: pointeur NULL). Si vous souhaitez créer un nouvel objet, appelez le return std::make_shared<Hello>(). En dehors de cela, l'utilisation d'un shared_ptr ne vous aide pas en ce qui concerne la collecte des ordures. Le comptage des références effectué par le pointeur intelligent repose sur l'appel du destructeur, un mécanisme C++. Comme la bibliothèque FFI s'interface avec le code C, cela n'arrivera pas, peu importe comment vous l'enroulerez pour le passer à LuaJIT (votre compilateur aurait dû vous avertir de l'utilisation de "extern" C "avec un type de retour typé) . Le moyen standard (si vous voulez compter sur la récupération de place) est de laisser le __gc metamethod appeler une fonction faisant le delete du côté C++. C'est le chemin C: Vous avez alloué une ressource dans votre appel de fonction, vous êtes responsable de la libérer ensuite.

Je vous recommande d'écrire un wrapper simple autour de votre classe, en utilisant peut-être d'abord Lua API pur pour apprendre les bases. Passez à l'emballage shared_ptr plus tard, lorsque vous avez partagé des objets et que vous ne voulez pas faire la référence vous-même.

+0

Merci pour votre explication. –