Когда Python вызывает язык C, возвращаемое значение является ненормальным - PullRequest
4 голосов
/ 20 июня 2019

Когда Python вызывает язык C, возвращаемое значение является ненормальным (python3.6.5 call gcc)

Я попытался передать список в файл C.so и вернуть значение. Я тестировал язык C без проблем, но возвращаемое значение всегда менялось, когда я использую файл python call c.so, и иногда возвращаемые значения даже становятся отрицательным значением.

//part c
#include <stdio.h>
#include <math.h>

extern c;

float get_mod(float *array){
    int N=sizeof(array);
    int i;
    float mod=0;
    for(i=0;i<N;++i){
        mod=mod+pow(array[i],2);
    }
    mod=sqrt(mod);
    return mod;
}

float get_inner(float *array1,float * array2){
    int N;
    N=sizeof(array1);
    int i;
    float inner=0;
    for(i=0;i<N;i++){
        inner = inner+array1[i]*array2[i];
    }
    return inner;
}

int cos_sim(float *a,float *b){
    float get_mod(float *);
    float get_inner(float *,float *);

    float mod1;
    float mod2;
    float inner;
    float cs;

    mod1=get_mod(a);
    mod2=get_mod(b);
    inner=get_inner(a,b);
    cs=inner/(mod1*mod2);
    float result;
    result=cs*pow(10,3);

    int res=result;
    printf("%d\n",res);
    return res;
}

//part python
import ctypes
from ctypes import *
import numpy as np
import win32api

dll = ctypes.CDLL(r"E:\whywork\zldf\cosine_similarity_c.so")
cossim=dll.cos_sim
cossim.argtypes=[POINTER(c_float),POINTER(c_float)]
arr1 = np.array([1,2,3],dtype="float64")
arr2 = np.array([1,2,5],dtype="float64")
cossim.restype=c_int
result = cossim(arr1.ctypes.data_as(POINTER(c_float)),arr2.ctypes.data_as(POINTER(c_float)))
win32api.FreeLibrary(dll._handle)
print(result)

Я хочу знать, как установить возвращаемое значение, когда Python вызывает C

1 Ответ

1 голос
/ 20 июня 2019

Изменяемые значения являются результатом вашего кода C. Значение N, которое вы вычисляете, неверно, sizeof(arr1) сообщает вам размер байта указателя, а не количество элементов в нем. В вашем коде вы используете байты в вашем коде и байты, которые хранятся после массивов в памяти. Как отметил @Mathias Schmid в комментариях, вы должны добавить N в качестве параметра.

Вот код C:

#include <stdio.h>
#include <math.h>

extern "C"{

    float get_mod(float *array, unsigned int N){
        int i;
        float mod=0;
        for(i=0;i<N;i++){
            mod=mod+pow(array[i],2);
        }
        mod=sqrt(mod);
        return mod;
    }

    float get_inner(float *array1,float * array2, unsigned int N){
        int i;
        float inner=0;
        for(i=0;i<N;i++){
            inner = inner+array1[i]*array2[i];
        }
        return inner;
    }

    int cos_sim(float *a,float *b, unsigned int N){

        float mod1;
        float mod2;
        float inner;
        float cs;
        float result;
        int res;

        mod1=get_mod(a, N);
        mod2=get_mod(b, N);
        inner=get_inner(a,b, N);
        cs=inner/(mod1*mod2);

        result=cs*pow(10,3);

        res=result;
        printf("%d\n",res);
        return res;
    }
}

В Python я бы рекомендовал просто использовать import ctypes или from ctypes import *. Сначала это меня немного смутило. Я также обновил ваш код Python:

import ctypes
import numpy as np
import win32api

dll = ctypes.CDLL(r"E:\whywork\zldf\cosine_similarity_c.so")
cossim=dll.cos_sim
arr1 = np.array([1,2,3],dtype="float32")
arr2 = np.array([1,2,5],dtype="float32")

N = ctypes.c_uint(len(arr1))
result = cossim(arr1.ctypes.data_as(ctypes.POINTER(ctypes.c_float)),
                arr2.ctypes.data_as(ctypes.POINTER(ctypes.c_float)), N)

win32api.FreeLibrary(dll._handle)
print(result)

Когда я запускаю этот код, результат всегда одинаков (975)

...