2009-06-29 7 views
7

Existe-t-il un moyen simple de travailler avec des objets C++ directement à partir de C? Je veux exposer certaines classes de C++ à C ou à FFI (interface de fonction étrangère). Bien sûr, je peux écrire un truc comme ça:Code C++ et objets de C?

class Foo{ 
.... 
}; 

void *make_foo(...){ 
Foo *ptr = new Foo(..) 

return static_cast<void *>(ptr); 
} 

.. 

int *foo_method1(void *fooptr, ...){ 
Foo *ptr = static_cast<Foo*>(fooptr); 
} 

Mais il existe une méthode plus simple?

+0

Puis-je vous demander ce que cela a à voir avec Lisp? – Svante

+0

Cela fait partie d'une question plus générale d'exposer les classes C++ à Common Lisp par CFFI (ou FFI dépendant de l'implémentation Lisp). –

Répondre

8

Cela, en général, est la méthode la plus simple. N'oubliez pas que vous devrez également utiliser extern "C" sur toutes vos méthodes C "wrapper".

7

Vous y êtes presque. Préfixez vos fonctions autonomes avec extern "C" pour désactiver le name mangling du compilateur C++.

Par exemple:

extern "C" void *make_foo(...){ 
    Foo *ptr = new Foo(..) 

    return static_cast<void *>(ptr); 
} 
1

Il n'y a pas vraiment une façon plus simple de le faire. Vous pouvez utiliser SWIG pour aller dans une autre langue avec des types définis par l'utilisateur qui sont plus que des agrégats de données, mais en convertissant en C, vous devrez utiliser l'idée de C des objets.

1

Vous pouvez utiliser Verrazano/Fetter pour générer des liaisons CFFI pour le code C++. Mais cela nécessite GCC-XML et je ne suis pas sûr de sa portabilité.

1

Si c'est possible, alors vos classes dérivent d'une structure. Vous pouvez ensuite utiliser des pointeurs vers cette structure dans le code C:

// C++ code 
extern "C" struct Cfoo {}; 
extern "C" struct Cbar {}; 

class foo : public Cfoo {}; 
class bar : public Cbar {}; 

// C API 
extern "C" { 
    struct Cfoo; 
    struct Cbar; 
} 

Ce n'est pas strictement une erreur, mais au moins gcc met en garde contre la conversion entre les pointeurs avec différents types.

void foo (void) { 
    struct Cfoo * pf; 
    struct Cbar * pb; 
    pf = pb;  // gcc warns 
} 

Si vous ne pouvez pas hériter, utilisez une idée similaire, mais ont la structure C magasin un pointeur sur l'objet du C, et encore simplement déclarer avant les structures dans l'API C:

// C++ code 
class foo {}; 
class bar {}; 

extern "C" struct Cfoo { foo * pFoo; }; 
extern "C" struct Cbar { bar * pBar; }; 

// C API 
extern "C" { 
    struct Cfoo; 
    struct Cbar; 
} 

Le inconvénient ici est que la durée de vie de l'objet Cfoo et Cbar doit être pris en charge.