调用共享C ++函数时Python内核崩溃

时间:2017-04-09 10:54:59

标签: python c++ ctypes

我是C ++的新手,所以对任何愚蠢的人都道歉。错误。

我在C ++中创建了一个用于Python的共享对象。但是,当我尝试在Python中调用此函数时,内核崩溃了。

C ++文件如下:

#include <cmath>
#include <iostream>
#include <list>
#include <vector>

using namespace std;

extern "C" 
{
    vector<int> cplusplus(int n=3,int maximum=1000)
    {          
        int i,j,order,m,i1,i2,mag;
        vector<int> output(0);

        i=1;
        j=0;

        while (i/maximum<=1)
        {
            i=10*i;
            j=j+1;
        } 

        m=j-1;

        for (i1=1; i1<m+2; i1++)
        {
            mag=pow(10,(i1-1));
            i=0;

            while (i+mag*(n+1)<=maximum)
            {
                for (i2=i+mag*n; i2<i+mag*(n+1); i2++)
                {
                    output.push_back(i2-1);
                }
                i=i+10*mag;
            } 

            if(i+mag*(n+1)>maximum)
            {
                for (i2=i+mag*n; i2<maximum+1; i2++)
                {
                    output.push_back(i2-1);
                }   
            }
        } 

        return output;
    }
}

我使用:

创建.so文件
g++ -shared -o cplusplus.so cplusplus.cpp

我用Python调用C ++函数:

import ctypes

cpp=ctypes.cdll.LoadLibrary('/Users/.../cplusplus.so')
print cpp.cplusplus(n=3,maximum=1000)

当正确返回时,该函数应该返回1到1000之间包含3(即3,13,23,30,31,...)的所有数字的向量。但是,目前Python内核崩溃了。

我认为这与我在C ++文件中使用向量或内存泄漏有关。

提前感谢您的帮助!

3 个答案:

答案 0 :(得分:1)

ctypes不了解C ++类型,因此这里是一个在函数接口中仅使用C类型的函数版本。必须预先分配结果缓冲区,并按地址传入元素的数量。该函数使用计算向量的长度更新元素的数量,如果它可以将这些元素复制到结果缓冲区中,则返回1(成功),否则返回0(失败)。

请注意,代码算法不正确并返回错误的答案,但ctypes有效。

#include <cmath>
#include <iostream>
#include <list>
#include <vector>
using namespace std;

extern "C"
{
    __declspec(dllexport) int cplusplus(int n, int maximum, int* result, size_t* pLength)
    {
        int i, j, order, m, i1, i2, mag;
        vector<int> output(0);

        i = 1;
        j = 0;

        while(i / maximum <= 1)
        {
            i = 10 * i;
            j = j + 1;
        }

        m = j - 1;

        for(i1 = 1; i1 < m + 2; i1++)
        {
            mag = pow(10, (i1 - 1));
            i = 0;

            while(i + mag * (n + 1) <= maximum)
            {
                for(i2 = i + mag * n; i2 < i + mag * (n + 1); i2++)
                    output.push_back(i2 - 1);

                i = i + 10 * mag;
            }

            if(i + mag * (n + 1) > maximum)
            {
                for(i2 = i + mag * n; i2 < maximum + 1; i2++)
                    output.push_back(i2 - 1);
            }
        }

        if(output.size() > *pLength)
        {
            *pLength = output.size();
            return 0; // fail
        }

        *pLength = output.size();
        memcpy(result, output.data(), output.size() * sizeof(int));
        return 1; // success
    }
}
>>> from ctypes import *
>>> lib = CDLL('test')
>>> lib.cplusplus.argtypes = c_int,c_int,POINTER(c_int),POINTER(c_size_t)
>>> lib.cplusplus.restype = c_int
>>> arr = (c_int * 1000)()
>>> size = c_size_t(1000)
>>> lib.cplusplus(3,1000,arr,byref(size))
1
>>> size
c_ulonglong(300)
>>> list(arr[:size.value])
[2, 12, 22, 32, 42, 52, 62, 72, 82, 92, 102, 112, 122, 132, 142, 152, 162, 172, 182, 192, 202, 212, 222, 232, 242, 252,
262, 272, 282, 292, 302, 312, 322, 332, 342, 352, 362, 372, 382, 392, 402, 412, 422, 432, 442, 452, 462, 472, 482, 492,
502, 512, 522, 532, 542, 552, 562, 572, 582, 592, 602, 612, 622, 632, 642, 652, 662, 672, 682, 692, 702, 712, 722, 732,
742, 752, 762, 772, 782, 792, 802, 812, 822, 832, 842, 852, 862, 872, 882, 892, 902, 912, 922, 932, 942, 952, 962, 972,
982, 992, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 229, 230, 231, 232,
233, 234, 235, 236, 237, 238, 329, 330, 331, 332, 333, 334, 335, 336, 337, 338, 429, 430, 431, 432, 433, 434, 435, 436,
437, 438, 529, 530, 531, 532, 533, 534, 535, 536, 537, 538, 629, 630, 631, 632, 633, 634, 635, 636, 637, 638, 729, 730,
731, 732, 733, 734, 735, 736, 737, 738, 829, 830, 831, 832, 833, 834, 835, 836, 837, 838, 929, 930, 931, 932, 933, 934,
935, 936, 937, 938, 299, 300, 301, 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, 315, 316, 317, 318,
319, 320, 321, 322, 323, 324, 325, 326, 327, 328, 329, 330, 331, 332, 333, 334, 335, 336, 337, 338, 339, 340, 341, 342,
343, 344, 345, 346, 347, 348, 349, 350, 351, 352, 353, 354, 355, 356, 357, 358, 359, 360, 361, 362, 363, 364, 365, 366,
367, 368, 369, 370, 371, 372, 373, 374, 375, 376, 377, 378, 379, 380, 381, 382, 383, 384, 385, 386, 387, 388, 389, 390,
391, 392, 393, 394, 395, 396, 397, 398]
>>> size = c_size_t(200) # too small
>>> lib.cplusplus(3,1000,arr,byref(size))
0
>>> size
c_ulonglong(300)

答案 1 :(得分:0)

我想知道n和max是否是实际变量。试试吧:

Print cpp.cplusplus ()

尝试构建一个在c ++中显示向量的方法。所以你没有混合印刷语言方法。

答案 2 :(得分:0)

你需要告诉python你的函数的输入和返回类型是modular inverse。我很确定std :: vector不是选项的一部分,选项列在文档中。

这不是最快的最佳做法选项 我开始做的是将你的输入序列化为json,并将它们作为char_p传递给共享库,然后用c ++转换它们,并返回另一个char_p ......但当然这不是最快或最好的选项。

(如果您确实正确定义了类型,请编辑您的帖子,我将删除此答案)