将字符串数组从python传递到C并在for循环中使用(包含代码)

将字符串数组从python传递到C并在for循环中使用(包含代码),python,c,ctypes,Python,C,Ctypes,我试图将两个字符串数组从python传入C,在嵌套的for循环中使用它们,将它们与一个参数进行比较,如果两个字符串满足此参数,我将它们附加到C中的一个新字符串数组中。函数结束时,我返回新的比较字符串数组。这个函数是在python中使用CDLL调用的,这个新的字符串数组是在我的python脚本中使用的 #In Python: PyOne = ["Apple", "Orange", "Banana"] PyTwo = ["Cuc

我试图将两个字符串数组从python传入C,在嵌套的for循环中使用它们,将它们与一个参数进行比较,如果两个字符串满足此参数,我将它们附加到C中的一个新字符串数组中。函数结束时,我返回新的比较字符串数组。这个函数是在python中使用CDLL调用的,这个新的字符串数组是在我的python脚本中使用的

#In Python:

PyOne = ["Apple", "Orange", "Banana"]
PyTwo = ["Cucumber", "Mango", "Pineapple", "Apple"]
我已将这些代码翻译成以下代码,以便在我的C函数中使用:

#In Python:

PyOne = ["Apple", "Orange", "Banana"]
PyOne_bytes = []
for i in range(len(PyOne)):
    PyOne_bytes.append(bytes(PyOne[i], 'utf-8'))
One_array = (ctypes.c_char_p * (len(PyOne_bytes)+1))()
One_array[:-1] = PyOne_bytes

PyTwo = ["Cucumber", "Mango", "Pineapple", "Apple"]
PyTwo_bytes = []
for i in range(len(PyTwo)):
    PyTwo_bytes(bytes(PyTwo[i], 'utf-8'))
Two_array = (ctypes.c_char_p * (len(PyTwo_bytes)+1))()
Two_array[:-1] = PyTwo_bytes
c.mainForLoop.argtypes = [POINTER(c_char_p), POINTER(c_char_p)]
c.mainForLoop.restype = ctypes.c_char_p

print(c.mainForLoop(One_array, Two_array))
上面的代码将现有的Python字符串数组转换为可由C解释的数组

这是我的C函数:

// In C

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define SCALING_FACTOR 0.1
#include <ctype.h>

...

char ** mainForLoop(const char ** PyOne, const char ** PyTwo) {
    char ** matches = malloc(100 * sizeof(char*));
    size_t i = 0;
    size_t j = 0;
    for (i = 0; i < sizeof(PyOne)/sizeof(PyOne[0]); i++) {
        for (j = 0; j < sizeof(PyTwo)/sizeof(PyTwo[0]); j++) {
            double v = comparison(PyOne[i], PyTwo[i]);
            if (v > 4) {
                strcat(matches, (PyOne[i]));
                strcat(matches, (";"));
            }
        }
    }
    return matches;
}
例如,如果比较(“苹果”、“黄瓜”)=5(即>4),比较(“橙色”、“芒果”)=7(即>4),以及所有其他比较()<4,那么我会预期,由于以下原因

// In C
double v = comparison(PyOne[i], PyTwo[i]);
                if (v > 4) {
                    strcat(matches, (PyOne[i]));
                    strcat(matches, (";"));
                }
为了

但目前,这张照片显示:

>>> b'Apple;'
我不知道我的代码哪里做错了。我对C有点陌生,我已经尝试了我能想到的一切,任何帮助都将不胜感激,解释也将是ace

谢谢大家!

编辑: 以下是我的新代码:

// In C
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>


void free_list(char** list, size_t size) {
    for(size_t i = 0; i < size; ++i) if (list[i]) free(list[i]);
    free(list);
}

char ** mainForLoop(const char ** PyOne, const char ** PyTwo, size_t sizeOne, size_t sizeTwo) {
    size_t i = 0;
    size_t j = 0;

    char ** matches = malloc(sizeOne * sizeof(char *));

    char temp[100] = {0};

    for (i = 0; i < sizeOne; i++) {
        // Cleared on each pass
        temp[0] = 0;
        for (j = 0; j < sizeTwo; j++) {
            double v = similarity(PyOne[i], PyTwo[j]);
            if (v > 4) {
                // Works with the temp buffer
                strcat(temp, (PyOne[i]));
                strcat(temp, (";"));
                int size = strlen(temp) + 1; //+1 for null termination

                char * str = malloc(size);
                memcpy(str, temp, size);
                str[size-1] = 0; //Null termination

                matches[i] = str;
            }
        }
    }
    return matches;
    free_list(matches, sizeOne);
}



#In Python
dll = CDLL("c.file")
dll.mainForLoop.argtypes = POINTER(c_char_p),POINTER(c_char_p),c_size_t,c_size_t
dll.mainForLoop.restype = POINTER(c_char_p)
dll.free_list.argtypes = POINTER(c_char_p),c_size_t
dll.free_list.restype = None

def make_clist(lst):
    return (c_char_p * len(lst))(*[x.encode() for x in lst])

def mainForLoop(list1,list2):
    size = c_size_t()
    result = dll.mainForLoop(make_clist(list1),make_clist(list2),len(list1),len(list2))
    data = [x.decode() for x in result[:size.value]]
    dll.free_list(result,size.value)
    return data

list1 = ["Apple", "Orange", "Banana"]
list2 = ["Apple", "Mango", "Pineapple", "Apple"]
print(mainForLoop(list1,list2))
//在C中
#包括
#包括
#包括
#包括
无效自由列表(字符**列表,大小){
对于(size_t i=0;i4){
//使用临时缓冲区
strcat(temp,(PyOne[i]);
标准温度(“;”);
int size=strlen(temp)+1;//+1表示空终止
char*str=malloc(大小);
memcpy(str、temp、size);
str[size-1]=0;//空终止
匹配[i]=str;
}
}
}
返回比赛;
免费列表(匹配项,sizeOne);
}
#用Python
dll=CDLL(“c.file”)
dll.mainForLoop.argtypes=指针(c_char_p)、指针(c_char_p)、c_size_t、c_size_t
dll.mainForLoop.restype=指针(c_char_p)
dll.free\u list.argtypes=指针(字符),大小
dll.free_list.restype=None
def make_clist(lst):
返回(c_char_p*len(lst))(*[x.encode()表示lst中的x])
def mainForLoop(列表1、列表2):
尺寸=c_尺寸_t()
result=dll.mainForLoop(make_clist(list1)、make_clist(list2)、len(list1)、len(list2))
数据=[x.decode()表示结果中的x[:size.value]]
dll.free_列表(结果、大小、值)
返回数据
列表1=[“苹果”、“橘子”、“香蕉”]
列表2=[“苹果”、“芒果”、“菠萝”、“苹果”]
打印(mainForLoop(列表1、列表2))
然而,这返回:

[]

请注意,C中的“comparison()”函数是一个字符串距离计算,它通过比较两个字符串返回一个双精度值


非常感谢您的帮助。

这里有一个比您的配置更接近的示例。请注意,我的
main
函数仅用于运行示例,在您的情况下,它将是无用的

主要的修复方法是,我为每个新字符串分配内存,而您没有这样做(您为指针分配了内存,但没有为字符串本身分配内存)。为此,我首先在堆栈上使用一个100个字符的临时缓冲区(如果需要的话,可以使其更长),一旦知道字符串的长度,我就分配它(请注意,您为释放这些字符串和指针准备的函数(free_list)已经正确):

#包括
#包括
#包括
#包括
双重比较(常量字符*1,常量字符*2){
int try=rand()%12;
返回尝试;
}
char**mainForLoop(char**PyOne,char**PyTwo,int-sizeOne,int-sizewo){
尺寸i=0;
尺寸j=0;
//分配一个由N个字符串指针组成的数组,其中N是PyOne的大小
char**matches=malloc(sizeOne*sizeof(char*);
//临时缓冲区
字符温度[100]={0};
对于(i=0;i4){
//使用临时缓冲区
strcat(temp,(PyOne[i]);
标准温度(“;”);
int size=strlen(temp)+1;//+1表示空终止
//然后分配一个大小正确的字符串
char*str=malloc(大小);
memcpy(str、temp、size);
str[size-1]=0;//空终止
//并收集它
匹配[i]=str;
}
}
}
返回比赛;
}
无效自由列表(字符**列表,大小){
对于(size_t i=0;i对于(char i=0;i而言,提供的C代码不正确,因此下面是演示如何传递和返回字节数组的示例。此示例只是将这两个列表附加在一起。它还处理释放内存的问题,因此C中的内存分配不会导致内存泄漏

测试c:

\ifdef\u WIN32
#定义API_uudeclspec(dllexport)
#否则
#定义API
#恩迪夫
#包括
#包括
API字符**附加列表(常量字符**列表1,大小大小1,常量字符**列表2,大小2,大小*pSize){
字符**总数=malloc((大小1+大小2)*大小
// In C
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>


void free_list(char** list, size_t size) {
    for(size_t i = 0; i < size; ++i) if (list[i]) free(list[i]);
    free(list);
}

char ** mainForLoop(const char ** PyOne, const char ** PyTwo, size_t sizeOne, size_t sizeTwo) {
    size_t i = 0;
    size_t j = 0;

    char ** matches = malloc(sizeOne * sizeof(char *));

    char temp[100] = {0};

    for (i = 0; i < sizeOne; i++) {
        // Cleared on each pass
        temp[0] = 0;
        for (j = 0; j < sizeTwo; j++) {
            double v = similarity(PyOne[i], PyTwo[j]);
            if (v > 4) {
                // Works with the temp buffer
                strcat(temp, (PyOne[i]));
                strcat(temp, (";"));
                int size = strlen(temp) + 1; //+1 for null termination

                char * str = malloc(size);
                memcpy(str, temp, size);
                str[size-1] = 0; //Null termination

                matches[i] = str;
            }
        }
    }
    return matches;
    free_list(matches, sizeOne);
}



#In Python
dll = CDLL("c.file")
dll.mainForLoop.argtypes = POINTER(c_char_p),POINTER(c_char_p),c_size_t,c_size_t
dll.mainForLoop.restype = POINTER(c_char_p)
dll.free_list.argtypes = POINTER(c_char_p),c_size_t
dll.free_list.restype = None

def make_clist(lst):
    return (c_char_p * len(lst))(*[x.encode() for x in lst])

def mainForLoop(list1,list2):
    size = c_size_t()
    result = dll.mainForLoop(make_clist(list1),make_clist(list2),len(list1),len(list2))
    data = [x.decode() for x in result[:size.value]]
    dll.free_list(result,size.value)
    return data

list1 = ["Apple", "Orange", "Banana"]
list2 = ["Apple", "Mango", "Pineapple", "Apple"]
print(mainForLoop(list1,list2))
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>

double comparison(const char * one, const char * two) {
    int try = rand() % 12;
    return try;
}

char ** mainForLoop(char ** PyOne, char ** PyTwo, int sizeOne, int sizeTwo) {
    size_t i = 0;
    size_t j = 0;
    
    // Allocate an array of N string pointers where N is the size of PyOne
    char ** matches = malloc(sizeOne * sizeof(char *));
    // The temporary buffer
    char temp[100] = {0};
    
    for (i = 0; i < sizeOne; i++) {
        // Cleared on each pass
        temp[0] = 0;
        for (j = 0; j < sizeTwo; j++) {
            double v = comparison(PyOne[i], PyTwo[j]);
            if (v > 4) {
                // Works with the temp buffer
                strcat(temp, (PyOne[i]));
                strcat(temp, (";"));
                int size = strlen(temp) + 1; //+1 for null termination

                // Then allocates a string of the right size
                char * str = malloc(size);
                memcpy(str, temp, size);
                str[size-1] = 0; //Null termination

                // And collects it
                matches[i] = str;
            }
        }
    }
    return matches;
}


void free_list(char** list, size_t size) {
    for(size_t i = 0; i < size; ++i) if (list[i]) free(list[i]);
    free(list);
}


int main() {
    // Initializes random
    srand(time(0));
    int N = 3;
    char * PyOne[3] = {"Apple", "Orange", "Banana"};
    char * PyTwo[4] = {"Cucumber", "Mango", "Pineapple", "Apple"};
    
    char ** matches = mainForLoop(PyOne, PyTwo, N, 4);

    // Prints the result which is possibly (depending on random) :
    // "Apple; Orange; Banana;Banana;"

    for (char i=0; i<N; i++) printf("%s ", matches[i]);
    printf("\n");

    // Frees
    free_list(matches, N);
    return 0; 
}