2017-05-09 1 views
2

Je travaille sur une tâche d'apprentissage en profondeur dans Lua et j'ai besoin d'importer un flux d'images dans Lua à partir de C++. Le script C++ lit les données d'une mémoire partagée et j'ai le pointeur vers les images en C++. Je voudrais obtenir ce pointeur dans Lua et donner le flux d'image à mon réseau de neurones. Puisque Lua n'utilise pas de pointeurs, et pour ce qui est de mes recherches, le chemin à parcourir est de placer ce pointeur dans userdata et d'écrire des méthodes d'accès. Comme expliqué dans ce User Data With Pointer Example. Mon problème est que je dois alimenter le réseau de neurones avec des données de pixels brutes et jusqu'à présent le matériel disponible en ligne suggère que le traitement sur les données devrait être fait en C++ et il n'y a aucun moyen d'obtenir directement cet objet dans Lua.
Quelle devrait être la bonne approche ici? Comment puis-je obtenir des valeurs d'objet dans Lua à partir d'un pointeur en C++?Flux d'image de processus dans Lua en important un pointeur d'image à partir de C++

Répondre

2

Eh bien, vous devez rendre les données accessibles à Lua en de façon.

Je pense à quatre approches générales:

  1. convertir les données

    • écriture du code C (++) qui traverse les données pour créer un ensemble de données Lua structure en tables & valeurs primitives (booléens, nombres, chaînes)
    • conversion des données en un format d'échange (JSON, DDDC, ... ou dans le cas de données d'image: PNM/PAM) pour lequel vous avez du code des deux côtés ou peut trivialement écrire

    (je ne dirai pas plus sur ces options ici .)

  2. passait en tant que fonctions accesseurs userdata et d'écriture, de sorte que vous pouvez écrire le code de conversion en Lua au lieu de C (++)

  3. (uniquement pour les données sans pointeur, et les images sont généralement que) passer la zone de données brutes à Lua sous la forme d'une chaîne

  4. (luajit seulement) en utilisant ffi.cdef de déclarer C struct s qui correspondent à la en mémoire le format pour la conversion libre accès & (int, float, n'a pas d'importance - peut aussi travailler avec des pointeurs)

(2) est fondamentalement juste (1a) avec la plupart du code déplacé vers le côté Lua. (3) est la même chose avec le code d'accès libre (string.byte(data, i[, j]) et un groupe d'autres, nouvellement ajouté en 5.3: string.unpack(fmt, data[, startpos])). Avant de décider de l'une de ces approches, examinez le format souhaité par l'autre partie.

Peut-être vos données sont-elles déjà dans ce format, auquel cas vous n'auriez qu'à traverser le pointeur d'une manière ou d'une autre. (Peut-être qu'une fonction accepte une table Lua, mais peut-être y en a-t-il une qui accepte une chaîne ou un pointeur vers des données brutes.) Si cela s'applique, utilisez des données utilisateur (légères) ou des chaînes pour la communication.(Ce sera probablement le plus rapide, et si cette façon de transmettre les données n'existe pas encore envisager de demander en amont s'ils peuvent l'ajouter.)

À défaut, vous devrez toucher les données. La version de chaîne est potentiellement la plus facile, mais aussi probablement la plus lente. (Si les données sont un bloc contigu d'octets, vous pouvez simplement lua_pushlstring pour tout importer dans Lua, mais cela crée une copie de la "chaîne" interne à l'état Lua qui peut être relativement lente.) Après cela, vous pouvez utiliser le standard string handling functionality de Lua.

Si vous utilisez LuaJIT, c'est probablement une très bonne idée d'utiliser la bibliothèque ffi. Un très bref aperçu de ce que vous devrez peut-être (en utilisant une liste chaînée comme exemple):

ffi = require "ffi" 
-- sample structure, yours will differ 
ffi.cdef [[ 
    typedef struct Node_s { struct Node_s *next; int value; } Node; 
]] 

-- in your case you will get a pointer from C, which you can then 
-- ffi.cast("Node*", ptr) 
-- after that, you can access the fields (ptr.next, ptr.value etc.) 
-- we'll just use some dummy sample data here: 
do 
    local p = ffi.new("Node") 
    local q = ffi.new("Node") 
    p.next = q 
    p.value, p.next.value = 23, 42 
    ptr = tonumber(tostring(p):match(": (0x%x*)")) 
end 

data = ffi.cast("Node*", ptr) 
print("first value:", data.value) 
--> first value: 23 
print("second value:", data.next.value) 
--> second value: 42 
print("third value:", data.next.next.value) 
--> Segmentation fault [so be just as careful as you're in C(++)!] 

Enfin, si vous êtes sur la vanille Lua, vous voudrez peut-être utiliser (complet) userdata et accesseurs manuellement par écrit pour éviter la perte de vitesse due à la copie de données. (La donnée utilisateur complète est requise afin que vous puissiez définir une variable pour obtenir les accesseurs, mais cela peut simplement être un pointeur vers vos données externes.) Le livre "Programming in Lua" contient de bonnes informations (direct link to the relevant chapter .)

+0

Merci beaucoup pour cette réponse détaillée. J'essaie d'utiliser LuaJIT FFI et pour une raison quelconque mon code de démo ne me donne pas la sortie désirée. [Mon code C.] (Https://gist.github.com/waleedahmedrana/40af2196d72027af6d5d173a49371532) [Mon code Lua] (https://gist.github.com/waleedahmedrana/86dcccb50181ce5f88702a45bfa8ee95) La sortie devrait être « C Programmation " Mais il me donne cdata : 0x7ff59b084040 Qu'est-ce que je fais mal ici? – Waleed

+0

@Waleed Eh bien, vous avez déclaré & obtenu un pointeur (ou tableau) 'char'. Il ne peut pas être traduit automatiquement en une chaîne Lua, car cela rendrait impossible toute modification. (Dans Lua qui crée toujours une nouvelle chaîne, l'ancienne restera inchangée.Pas bon si vous essayez de communiquer à travers cette zone de mémoire.) Soit accéder aux octets individuels (rapide, pas de copie, etc.) ou utiliser [' ffi.string'] (http://luajit.org/ext_ffi_api.html#ffi_string) pour créer une copie comme une chaîne Lua normale. – nobody

+0

Merci. Cela a fonctionné! – Waleed