Χρησιμοποιώντας SWIG και το API Python / C για να τυλίξει μια λειτουργία η οποία λαμβάνει μια λίστα Python των C περιπτώσεις κατηγορίας ++

ψήφοι
1

Θέλω να τυλίξει ένα C ++ ρουτίνα που παίρνει σε μια σειρά από περιπτώσεις κατηγορίας. Έχω πρόβλημα να πάρει αυτό για να συνεργαστεί με Γουλιά και θα εκτιμούσα οποιαδήποτε βοήθεια που μπορεί να προσφέρει. Έχω προσπαθήσει να βράσει το θέμα μέχρι την ουσία του μέσα από ένα απλό παράδειγμα.

Η κεφαλίδα test.hορίζεται ως εξής:

/* File test.h */
#include <stdlib.h>
#include <stdio.h>

class Test {
  private:
    int my_value;
  public:
    Test(int value);
    void printTest();
};

void print_tests(int num_tests, Test** tests);

Η υλοποίηση ορίζεται στην test.cppκατωτέρω:

/* File test.cpp */
#include test.h

void print_tests(int num_tests, Test** tests) {
  for (int i=0; i < num_tests; i++)
    tests[i]->printTest();
}

Test::Test(int value) { 
  my_value = value; 
}

void Test::printTest() { 
  printf(my value is %d\n, my_value); 
}

Έχω γράψει ένα αρχείο διεπαφής SWIG test.iνα προσπαθήσει να φιλοξενήσει αυτή τη ρουτίνα, ώστε να μπορώ να περάσουν σε μια λίστα Python των Testπεριπτώσεων κατηγορίας:

%module test

%{
  #define SWIG_FILE_WITH_INIT
  #include test.h
%}

%typemap(in) (int num_tests, Test** tests) {

  if (!PyList_Check($input)) {
    PyErr_SetString(PyExc_ValueError, Expected a Python list of Tests);
    return NULL;
  }

  $1 = PySequence_Length($input);  // num_tests
  $2 = (Test**) malloc(($1) * sizeof(Test*)); // tests

  /* Loop over tests */
  for (int i = 0; i < $1; i++) {
    /* Extract the value from the list at this location */
    PyObject* o = PyList_GetItem($input,i);
    $2[i] = (Test*) o;
  }
}

%include test.h

Θα τυλίξτε τις ρουτίνες και την κατάρτιση του SWIG που δημιουργείται κωδικό περιτύλιγμα, και να τον συνδέσετε ως μια κοινή βιβλιοθήκη ως εξής:

> swig -python -c++ -o test_wrap.cpp test.i
> gcc -c test.cpp -o test.o -fpic -std=c++0x
> gcc -I/usr/include/python2.7 -c test_wrap.cpp -o test_wrap.o -fpic -std=c++0x
> g++ test_wrap.o test.o -o _test.so -shared -Wl,-soname,_test.so

Στη συνέχεια θέλουν να είναι σε θέση να κάνετε τα εξής μέσα από την Python:

import test

test1 = test.Test(2)
test2 = test.Test(1)
test.print_tests([test1, test2, test1])

Αν τρέξω αυτό το σενάριο example.py, όμως, παίρνω το ακόλουθο αποτέλεσμα:

> python example.py 
my value is 3
my value is 2
my value is 3

Οποιεσδήποτε ιδέες γιατί έχω 2και 3ως έξοδο, παρά το 1και 2τα οποία διατέθηκαν για την Testκατηγορία κατασκευαστή; Πιστεύω ότι αυτό είναι ένα θέμα με το αρχείο διεπαφής SWIG μου περνώντας δείκτες στις SWIG Testπεριπτώσεις κατηγορίας περιτύλιγμα και όχι το C ++ Testπεριπτώσεις της κατηγορίας, αλλά δεν είμαι σίγουρος. Οποιαδήποτε βοήθεια θα εκτιμηθεί ιδιαίτερα!

Δημοσιεύθηκε 09/10/2014 στις 09:24
πηγή χρήστη
Σε άλλες γλώσσες...                            


1 απαντήσεις

ψήφοι
0

Νομίζω ότι το πρόβλημα έγκειται στην προσπάθεια να ρίξει άμεσα το PyObject oνα Test *. Δεν θέλουμε το δείκτη του PyObjectπου είναι SwigPyObject, αλλά του Test*οποίου είναι κάπου στο εσωτερικό του SwigPyObject. Τι θα μπορούσατε να κάνετε είναι να χρησιμοποιήσετε ξανά SWIG_ConvertPtr(ο τρόπος γουλιά το κάνει στην παράγεται περιτύλιγμα):

%typemap(in) (int num_tests, Test** tests) {

  if (!PyList_Check($input)) {
    PyErr_SetString(PyExc_ValueError, "Expected a Python list of Tests");
    return NULL;
  }

  $1 = PySequence_Length($input);  // num_tests
  $2 = (Test**) malloc(($1) * sizeof(Test*)); // tests

  /* Loop over tests */
  for (int i = 0; i < $1; i++) {
    /* Extract the value from the list at this location */
    PyObject* o = PyList_GetItem($input,i);
    void *p1 = 0;
    SWIG_ConvertPtr(o, &p1,SWIGTYPE_p_Test, 0 |  0 );
    $2[i] = (Test*) p1;
  }
}
Απαντήθηκε 09/10/2014 στις 13:38
πηγή χρήστη

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more