6

Python から C++ 関数を呼び出したいのですが、この C++ 関数は char* をパラメーターとして取り、文字列を返します。以下は私のコードです。

ラッパー.cpp

#include <Python.h>
#include <string>
#include <iostream>

using namespace std;

extern "C"
string return_string(char* name){
    cout<<strlen(name)<<endl;
    cout<<name<<endl;
    string s = "hello ";
    s += name;
    return s;
}

wrapper.cpp を example.so にコンパイルします。

g++ -fPIC wrapper.cpp -o example.so -shared -I/usr/include/python2.7/

wrapper.py

import os
from ctypes import *

lib = cdll.LoadLibrary('./example.so')
lib.return_string.restype = c_char_p
lib.return_string.argtypes = [c_char_p]
name = create_string_buffer("Tom")
s = lib.return_string(name);
print s
print name

ここに私の出力があります

18
��H�L�l���A���
1
<ctypes.c_char_Array_4 object at 0x7f5f480be710>

それを機能させる方法は?

4

1 に答える 1

11

これは ctypes とは関係ありません。あなたの C++ コード自体は無効です。extern "C"を返す関数を定義することはできませんstring

同じライブラリを使用する C++ プログラムでの簡単なテストでは、ガベージも出力されます。

また、コンパイルして何が起こるかを確認できるようにstring、同じレイアウトで呼び出されるものを定義する C プログラムも作成しました。std::stringまた、ガベージを出力し、セグメンテーション違反を起こし~stringます。

したがって、Python プログラムがガベージを出力することは驚くべきことではありません。

マイナーな変更により、すべてが機能します。

extern "C"
const char *return_string(char* name){
    cout<<strlen(name)<<endl;
    cout<<name<<endl;
    static string s = "hello ";
    s += name;
    return s.c_str();
}

私はこの出力を得る:

3
Tom
hello Tom
<ctypes.c_char_Array_4 object at 0x11011c7a0>

(または、C++ バージョンから、同じことですが、最後の行に "Tom" があります。)

もちろん、明らかな理由から、これはあまり良い解決策ではありませんが、戻ることstringが問題であることを示しています。

C++ コードをコンパイルしようとしたときに、g++-4.5 と clang-apple-4.0 の両方で、まさにこの問題について警告されました (ただし、g++-apple-4.2 では、追加の -W フラグを追加しない限り、警告されませんでした)。コンパイラが警告を出すとき、多くの場合、それが「なぜ私のコードはコンパイルされているのに間違ったことをするのか」に対する答えです。

あなたのコードには他にもいくつか問題があります:

  • .cpp ファイルで Python から何も使用しません。そして一般に、使用の要点はctypes、C または C++ コードが Python について何も知らなくてもよいようにすることです。それを知っているのはあなたのPythonコードです。したがって、含めたりリンクしたりしないでください。
  • char*変更する予定がない場合、非 const を使用することは一般的に悪い考えです。私の C++ ドライバーは、const_cast<char*>(name.c_str())ではなく で呼び出す必要がありましたname.c_str()。また、これにより、コンパイラが実行中の他のことを認識できなくなる可能性があります。

上記の C++ ドライバーは次のとおりです。

#include <iostream>
#include <string>
using namespace std;

extern "C" string return_string(char* name);

int main(int argc, char *argv[]) {
  string name("Tom");
  string s(return_string(const_cast<char *>(name.c_str())));
  cout << s << "\n";
  cout << name << "\n";
  return 0;
}

また、さまざまな最適化設定をいじったり、コードを少し再構成したりすると、私の C++ ドライバーで、コードが実際に機能することもあれば、ガベージを出力することもあれば、segfault になることもあります。私の最初の推測では、~string呼び出しがどこでインライン化されるかによって異なりますが、実際には詳細は問題ではありません。コードは機能しないはずなのに機能しないので、誰がその理由を気にしますか?

于 2012-09-19T18:00:13.193 に答える