8

[1,2,3,4]C++ スクリプトからpython リストを取得したいと思います。ベクトルを返す C++ スクリプトを作成しました。

SWIG/SIP/Cython/その他を使わずに両端を接続するには?

C++を.exeまたはelfファイルにコンパイルしてからコマンドラインから呼び出し、.exeにベクトルを含む.txtを作成させ、Pythonで読み込む方が簡単でしょうか?

私の要点は、巨大なデータに対して重い計算を行うために必要なのは、C++ の非常に小さな関数だけです。これを行うための最も簡単で最短の方法は何でしょうか?

編集: 例を挙げます。Python はファイル名の文字列 ("foo.txt") を C++ に渡します。C++ はファイルのコンテキスト (200,000 行 x 300 列) を読み取り、欠落を数え、行ごとの欠落の量を Python に返します。これにより、200,000 個の数値のリストが生成されます。両者の間でこのコミュニケーションをどのように行うのですか?

完全を期すために、これは私がまだどのように進むべきかについて疑問に思っていることです:

  • Python ファイル名文字列を C++ に渡す
  • C++ で Python 文字列を受け取る
  • 完了 C++ でベクトルを作成
  • ベクトルを Python に返す
  • Python でベクトルを受け取る
4

5 に答える 5

6

これはおそらく今は意味がなく、他の質問にも似たようなものを投稿しましたが、このバージョンを Python 2.7 と C ではなく Python 3.3 と C++ に適合させました。

Python リスト オブジェクトを取得したい場合、非常に長くなる可能性があるリスト (200,000 項目) を作成している場合、おそらく、C++ コードで Python リストを作成する方が効率的ですstd::vector。後でそれを Python リストに変換します。

他の質問のコードに基づいて、次のようなものを使用することをお勧めします...

// foo.cpp
#include <python3.3/Python.h>
#include <fstream>
#include <string>
using namespace std;

extern "C"
{
    PyObject* foo(const char* FILE_NAME)
    {
        string line;
        ifstream myfile(FILE_NAME);
        PyObject* result = PyList_New(0);

        while (getline(myfile, line))
        {
            PyList_Append(result, PyLong_FromLong(1));
        }

        return result;
    }
}

...でコンパイル...

$ g++ -fPIC -shared -o foo.so foo.cpp -lpython3.3m

...そして使用例...

>>> from ctypes import *
>>> foo = CDLL('./foo.so')
>>> foo.foo.restype = py_object
>>> foo.foo(b'foo.cpp')
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]

...ただし、既存の を Python リストに変換する必要がある場合は、ベクトルの長さを に渡し、代わりに を使用するstd::vectorことで、Python リストに必要なメモリを事前に割り当てることができます。PyList_New()PyList_SetItem()PyList_Append()

私が考えることができる唯一の他の方法は...

  1. Python で RAM のブロックを事前に割り当て、C++ 関数に値を入力させるには、qarma の回答のように、割り当てる RAM の量を事前に知っておく必要があります。任意の値を選択することもできますが、ファイル内の行数が事前にわからない場合、この数は大きすぎるか小さすぎる可能性があります。

  2. C++ でヒープを割り当て、std::vector最初の要素へのポインターと要素の数を返すには、2 つ目の関数を記述して RAM を解放する必要があります。

いずれにせよ、「返された」配列を Python リストに変換するオーバーヘッドがまだ残っているため、自分で行うこともできます。

于 2013-06-03T21:20:36.507 に答える
6

エントリ ポイントextern "C"を定義して使用しますctypes

開始するための例を次に示します。データは Python から渡され、C++ コードがデータを並べ替え、Python が結果を返します。

#include <sys/types.h>
#include <algorithm>

extern "C" {
    void foo(float* arr, size_t len);
}

void foo(float* arr, size_t len)
{
    // if arr is input, convert to C++ array

    // crazy C++ code here
    std::sort(arr, arr+len);

    // if arr is output, convert C++ array to arr
}

コードを共有オブジェクト (Linux では libxxx.so、win では libxxx.dll、osx では libxxx.dylib) にコンパイルし、動的にロードして ctypes 経由でデータを入出力します:

import ctypes
import posix

# Darwin .dylib; Linux .so; Windows .dll; use sys.platform() for runtime detection
libxxx = ctypes.CDLL("./libxxx.so")
libxxx.foo.argtypes = [ctypes.POINTER(ctypes.c_float), ctypes.c_size_t]
libxxx.foo.restype = None

data = ctypes.ARRAY(ctypes.c_float, 100)()

# write someting into data[x]
import random
for i in range(100): data[i] = random.random()
print data[:3], "...", data[-3:]

libxxx.foo(data, len(data))

# read out from data[x]
print data[:3], "...", data[-3:]

素晴らしい点ctypesは、Python 2.5 以降にバンドルされていることです。追加のライブラリは必要ありません。

より高度なものを使用したい場合は、 をご覧くださいcffi

于 2013-05-29T20:27:02.083 に答える
3

Python で subprocess モジュールを使用して、C++ exe ファイルから出力を読み取ることができます。例えば:

c++ ファイル:

#include <iostream>
using namespace std;
int main()
{
    int a[]={1,2,3,4};
    cout<<"[";
    for(int i=0; i<3; i++)
        cout<<a[i]<<",";
    cout<<a[3]<<"]";
    return 0;
}

次に、Pythonスクリプトは次のようになります。

import subprocess
a=subprocess.check_output("c++compiledfile")
l=eval(a)
print l
于 2013-05-22T15:56:20.510 に答える
3

あなたは正しい軌道に乗っています。

実行可能ファイルが 2 つありますか?

中間ファイルに保存することをお勧めします。ファイルをロックし、C++ コードから書き込みます。ロックを解除して Python から読み取ります。

Python から実行したいだけの場合は、いつでも Python の拡張を検討できます。

C++ による Python の拡張

ソケットを介して行うオプションもありますが、リストを渡すだけの場合、これは少しやり過ぎかもしれません。

于 2013-05-22T13:35:23.007 に答える
0

プロセス間通信で文字列を操作できます
。Python で subprocess.check_output() 関数を使用して C++ プログラムの出力をチェックし、ファイル名を引数として渡します。

Python のコード:

import subprocess
from time import clock


ti=clock()
txt_fname='foo.txt'
# pass the filename string to a c++ program, and receive vector in python
output=subprocess.check_output(["./prog", txt_fname])
result = eval(output)   # convert the str_result to a vector/list
tf=clock()

print(result)
print(format(tf-ti, '.3f'))

C++ コード:

#include <stdio.h>
#include <stdlib.h>
#include <iostream>
#include <vector>


int main(int argc, char *argv[])
{
    // receive python string in c++
    char* txt_fname = argv[1];

/*  // read matrix from file in c++
    FILE *f_matrix = fopen(txt_fname, "r");
    // ... [done by the question's author!]
    if (f_matrix!=NULL){
        fclose(f_matrix);
    }*/

    // create the vector in c++
    int n=200000;
    std::vector<int> vect(n);
    // or:  int vect[];
    // ... [done by the question's author!]

    // return the vector to python
    std::cout << "[";
    for (int i=0; i<n; i++)
        std::cout << vect[i] << ", ";
    std::cout << "]";

    return 0;
}

EDIT:タイマーを追加し、「ast.literal_eval()」を「eval()」に置き換えます。実際、この場合のeval()の方が高速で、python 3.3と互換性があるためです。

于 2013-06-04T03:11:17.777 に答える