2017-10-20 43 views
0

J'ai des problèmes avec swig et char ** comme pointeur vers une variable char * (pas comme une liste de char * !!!). Je ne pouvais pas trouver un moyen d'enrouler le pointeur sur un char *.swig char ** comme un pointeur vers un char *

Le but est d'écrire le résultat de la concaténation dans le char * référencé par le pointeur.

Voici mon code:

fichier pointers.cpp:

#include "pointers.h" 
#include <string.h> 
#include <stdlib.h> 
#include <stdio.h> 

void conc(char *str1, char *str2, char **res){ 
    char *aux = (char *)malloc(strlen(str1)+strlen(str2)+1); 
    strcpy(aux,str1); 
    strcat(aux,str2); 
    strcpy(*res,aux); 
    free(aux); 
} 

Fichier pointers.h

void conc(char *str1, char *str2, char **res) 

Fichier pointers.i

%module pointers 
%{ 
#define SWIG_FILE_WITH_INIT 
#include "pointers.h" 
%} 

%include "typemaps.i" 
%include "cpointer.i" 
%include "cstring.i" 

%pointer_functions(char *, charp); 
extern void conc(char *str1, char *str2, char **res); 

de configuration du fichier .py:

from distutils.core import setup, Extension 


pointers_module = Extension('_pointers', 
         sources=['pointers_wrap.cxx', 'pointers.cpp'], 
         ) 

setup (name = 'pointers', 
    version = '0.1', 
    author  = "SWIG Docs", 
    description = """Simple swig example from docs""", 
    ext_modules = [pointers_module], 
    py_modules = ["pointers"], 
    ) 

Enfin, le principal python:

import pointers 

result = new_charp() 
pointers.conc("Hello ","World!", result); 
print(result) 
delete_charp(result) 

Et tous sont compilés avec les commandes du terminal:

swig -c++ -python pointers.i 
python setup.py build_ext --inplace 

Mais l'erreur de retour du compilateur:

pointers_wrap.cxx: In function ‘char** copy_charp(char*)’: 
pointers_wrap.cxx:3124:58: error: invalid static_cast from type ‘char*’ to    
type ‘const char*&’ return (new char *(static_cast< const char *& >(value))); 
                     ^
error: command 'gcc' failed with exit status 1 

Toute aide?

[MISE À JOUR DE LA QUESTION]

Comme suggéré par @MarkTolonen j'ai essayé de changer le fichier pointers.i de la manière suivante:

Nouveau fichier pointers.i:

%module pointers 

%{ 
#include "pointers.h" 
%} 

// This input typemap declares that char** requires no input parameter. 
// Instead, the address of a local char* is used to call the function. 
%typemap(in,numinputs=0) char** (char* tmp) %{ 
    $1 = &tmp; 
%} 

// After the function is called, the char** parameter contains a malloc'ed char* pointer. 
// Construct a Python Unicode object (I'm using Python 3) and append it to 
// any existing return value for the wrapper. 
%typemap(argout) char** %{ 
    PyObject *obj = PyUnicode_FromString(*$1); 
    $result = SWIG_Python_AppendOutput($result,obj); 
%} 

// The malloc'ed pointer is no longer needed, so make sure it is freed. 
%typemap(freearg) char** %{ 
    free(*$1); 
%} 

// Now that the typemap exists, let swig wrap the header. 
%include "pointers.h" 

compiler avec:

swig -c++ -python pointers.i 
g++ --std=c++11 -fPIC -c pointers.cpp 
g++ --std=c++11 -fPIC -c pointers_wrap.cxx -I/usr/local/include/python3.6m 

Et puis je suis l'erreur:

In function ‘PyObject* _wrap_conc(PyObject*, PyObject*):` 
pointers_wrap.cxx:3618:1: error: jump to label ‘fail’ [-fpermissive] 
fail: 
pointers_wrap.cxx:1222:49: note: from here 
#define SWIG_fail     goto fail 

pointers_wrap.cxx:2999:68: note: in expansion of macro ‘SWIG_fail’ 
#define SWIG_exception_fail(code, msg) do { SWIG_Error(code, msg); SWIG_fail; } while(0) 
pointers_wrap.cxx:3603:5: note: in expansion of macro ‘SWIG_exception_fail’ 
SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "conc" "', argument " "2"" of type '" "char *""'"); 

pointers_wrap.cxx:3609:8: note: crosses initialization of ‘_object* obj’ 
auto obj = PyUnicode_FromString(*arg3); 
pointers_wrap.cxx:3618:1: error: jump to label ‘fail’ [-fpermissive] 
fail: 

pointers_wrap.cxx:1222:49: note: from here 
#define SWIG_fail      goto fail 
pointers_wrap.cxx:2999:68: note: in expansion of macro ‘SWIG_fail’ 
#define SWIG_exception_fail(code, msg) do { SWIG_Error(code, msg); SWIG_fail; } while(0) 
pointers_wrap.cxx:3598:5: note: in expansion of macro ‘SWIG_exception_fail’ 
SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "conc" "', argument " "1"" of type '" "char *""'"); 

pointers_wrap.cxx:3609:8: note: crosses initialization of ‘_object* obj’ 
auto obj = PyUnicode_FromString(*arg3); 

pointers_wrap.cxx:3618:1: error: jump to label ‘fail’ [-fpermissive] 
fail: 
pointers_wrap.cxx:1222:49: note: from here 
#define SWIG_fail     goto fail 
pointers_wrap.cxx:3595:62: note: in expansion of macro ‘SWIG_fail’ 
if (!PyArg_ParseTuple(args,(char *)"OO:conc",&obj0,&obj1)) SWIG_fail; 
pointers_wrap.cxx:3609:8: note: crosses initialization of ‘_object* obj’ 
auto obj = PyUnicode_FromString(*arg3); 

Cela fonctionne sur ce système d'exploitation Windows, mais pas sur mon ubuntu. Quelqu'un peut-il dire comment y faire face. Je ne sais vraiment pas comment résoudre mes problèmes de pointeurs.

+0

où est pointers_wrap.cxx vient? > 3k lignes dans un seul fichier me donne le vertige même sans voir le fichier – user463035818

+0

ouais, il est créé en exécutant le fichier setup.py. C'est le fichier créé automatiquement par swig pour construire le fichier wrapper. Et c'est nécessaire dans la création du module swig. – lorsp000

Répondre

0

De la documentation SWIG 3.0, à la fin de §9.2.1 cpointer.i:

Note: None of these macros can be used to safely work with strings (char * or char **).

donc vous devrez recourir à typemaps. Voici un exemple:

pointers.cpp

je devais changer légèrement votre source. Un argument char** doit renvoyer le pointeur alloué, et non le libérer:

#include <string.h> 
#include <stdlib.h> 
#include "pointers.h" 

void conc(char *str1, char *str2, char **res){ 
    *res = (char *)malloc(strlen(str1)+strlen(str2)+1); 
    strcpy(*res,str1); 
    strcat(*res,str2); 
} 

pointeurs.h

void conc(char *str1, char *str2, char **res); 

pointers.i

Cette version du fichier rasade déclare les typemaps pour gérer l'argument de sortie char**.

%module pointers 

%{ 
#include "pointers.h" 
%} 

// This input typemap declares that char** requires no input parameter. 
// Instead, the address of a local char* is used to call the function. 
%typemap(in,numinputs=0) char** (char* tmp) %{ 
    $1 = &tmp; 
%} 

// After the function is called, the char** parameter contains a malloc'ed char* pointer. 
// Construct a Python Unicode object (I'm using Python 3) and append it to 
// any existing return value for the wrapper. 
%typemap(argout) char** (PyObject* obj) %{ 
    obj = PyUnicode_FromString(*$1); 
    $result = SWIG_Python_AppendOutput($result,obj); 
%} 

// The malloc'ed pointer is no longer needed, so make sure it is freed. 
%typemap(freearg) char** %{ 
    free(*$1); 
%} 

// Now that the typemap exists, let swig wrap the header. 
%include "pointers.h" 

test.py

import pointers 
result = pointers.conc('Hello ','World!'); 
print(result) 

Sortie

Hello World!

+0

merci! Mais en compilant votre code, j'ai eu quelques erreurs, toutes se référant 'jump to label 'fail'' dans la fonction' PyObject * _wrap_conc (PyObject *, PyObject *) 'et une note:' crosses initialisation de'object * obj' sur 'obj auto ='. Sais-tu pourquoi? – lorsp000

+0

@ Lorsp000 Votre compilateur C++ est ancien. Changez automatiquement le type de retour de PyUnicodeFromString. Je pense que c'est PyObject *. –

+0

J'ai essayé de changer le type de retour, mais ne fonctionne toujours pas. D'un autre côté, j'ai une version g ++ 6.3.0, est-ce trop vieux pour PyUnicodeFromString? – lorsp000