J'écris maintenant des wrappers pour les fonctions C++, de sorte qu'ils peuvent être utilisés à partir du code C. L'idée est de compiler les fichiers cpp en utilisant g ++ et les fichiers c en utilisant gcc, puis de les lier ensemble (!), Mais en n'exposant que les fonctions nécessaires aux programmes C, en les rendant disponibles dans un en-tête fichier 'test.h', comme si (ou peut-être test.hpp?):Défis dans l'écriture des wrappers pour les fonctions C++ afin qu'ils puissent être utilisés à partir du code C
(Notez que je ne pas exposer la fonction 'vecteur Tokenize (const string & str, string const & delimiters)')
test.h:
/* Header can be read by both C+ and C compilers, just the way we want! */
#ifndef TEST_H
#define TEST_H
#ifdef __cplusplus
extern "C" {
#endif
#if defined(__STDC__) || defined(__cplusplus)
extern int TokenizeC(const char* text, const char* delim, char ***output); /* ANSI C prototypes */
extern void reclaim2D(char ***store, unsigned int itemCount);
#endif
#ifdef __cplusplus
}
#endif
#endif /* TEST_H */
test.cpp:
#include <string>
#include <iostream>
#include <vector>
#include <assert.h>
#include "test.h"
using namespace std;
vector<string> Tokenize(const string& str,const string& delimiters)
{
vector<string> tokens;
string::size_type delimPos = 0, tokenPos = 0, pos = 0;
if(str.length() < 1) return tokens;
while(1)
{
delimPos = str.find_first_of(delimiters, pos);
tokenPos = str.find_first_not_of(delimiters, pos);
if(string::npos != delimPos)
{
if(string::npos != tokenPos)
{
if(tokenPos < delimPos) tokens.push_back(str.substr(pos,delimPos-pos));
else tokens.push_back("");
}
else tokens.push_back("");
pos = delimPos + 1;
}
else
{
if(string::npos != tokenPos) tokens.push_back(str.substr(pos));
else tokens.push_back("");
break;
}
}
return tokens;
}
int TokenizeC(const char* text, const char* delim, char ***output)
{
if((*output) != NULL) return -1; /* I will allocate my own storage, and no one tells me how much. Free using reclaim2D */
vector<string> s = Tokenize(text, delim);
// There will always be a trailing element, that will be blank as we keep a trailing delimiter (correcting this issue would not be worth the time, so this is a quick workaround)
assert(s.back().length() == 0); // This will be nop'ed in release build
s.pop_back();
(*output) = (char **)malloc(s.size() * sizeof(char *));
for(vector <string>::size_type x = 0; x < s.size(); x++)
{
(*output)[x] = strdup(s[x].c_str());
if(NULL == (*output)[x])
{
// Woops! Undo all
// TODO : HOW to test this scenario?
for(--x; x >= 0; --x)
{
free((*output)[x]);
(*output)[x] = NULL;
}
return -2;
}
}
return x; /* Return the number of tokens if sucessful */
}
void reclaim2D(char ***store, unsigned int itemCount)
{
for (int x = 0; itemCount < itemCount; ++x)
{
free((*store)[x]);
(*store)[x] = NULL;
}
free((*store));
(*store) = NULL;
}
poc.c:
#include <stdio.h>
#include "test.h"
int main()
{
const char *text = "-2--4--6-7-8-9-10-11-", *delim = "-";
char **output = NULL;
int c = TokenizeC(text, delim, &output);
printf("[*]%d\n", c);
for (int x = 0; x < c; ++x)
{
printf("[*]%s\n", output[x]);
}
reclaim2D(&output, c);
return 0;
}
Avez-vous remarqué quelque chose de mal?
Pour commencer, quand je courais ce programme, je suis "symbole de code Insatisfait '__gxx_personality_v0'"
Heureusement, il y a quelque chose ici: What is __gxx_personality_v0 for?
Une fois que je courais g ++ avec des options "-fno-exceptions -fno-rtti ", la sortie échoue maintenant avec" symbole de données Insatisfait '_ZNSs4_Rep20_S_empty_rep_storageE' "
Bien sûr, les deux environnements (celui à compiler - HP-UX B.11.23 ia64 et celui pour exécuter le binaire sur - HP-UX B.11.31 ia64) ont des versions de bibliothèque différentes (mais la même architecture), et cela ne devrait pas être un raison des erreurs.
Je voudrais également tester le cas marqué par "// TODO: comment tester ce scénario?", Mais cela peut attendre pour le moment.
Des pointeurs?
Voici ce que j'ai fait: g ++ -c -fPIC -Wall -Wuninitialized -fno-exceptions -fno-rtti -O - D__hpuxita -mlp64 -I $ (INCLUDEPATH) $ <; gcc -c -fPIC -Wall -Wstrict-prototypes -Wuninitialized -O -D__hpuxita -mlp64 -I $ (INCLUDEPATH) $ <; gcc -AA -AA -mlp64 -shared -L $ (LIBPATH) $ (OBJS) -o $ (APP) – PoorLuzer
Ah oui - toute compilation se fait sur une seule machine. – PoorLuzer
+1, le problème est la dernière ligne là, vous devriez lier avec g ++ pas gcc qui inclura tous les trucs C++ nécessaires par défaut. –