python 向C接口傳遞結構體數組、結構體

c源碼 1.c

#include <stdio.h>
#include <string.h>
#include "1.h"


int add(int a, int b)
{
    return a+b;
}
#if 0
int add_stus(STUDENT *data, int count)
{
    int i = 0;
    printf("count=[%d]\n",count);
    for (i; i < count; i++)
    {
            printf("age=%d\n", data->age);
            printf("name=%s\n", data->name);
            printf("color=%s\n", data->color);
            printf("alarmtime=%ld\n", data->alarmtime);
    }

    return 1;
}

int add_stu(STUDENT *data)
{
    printf("age=%d\n", data->age);
    printf("name=%s\n", data->name);
    printf("color=%s\n", data->color);
    printf("alarmtime=%ld\n", data->alarmtime);
    return 1;
}

int add_data(STUDENT data)
{
    printf("age=%d\n", data.age);
    printf("name=%s\n", data.name);
    printf("color=%s\n", data.color);
    printf("alarmtime=%ld\n", data.alarmtime);
    return 1;
}
#endif

int add_stus(STUDENT *data, int count)
{
    int i = 0;
    printf("count=[%d]\n",count);
    for (i; i < count; i++)
    {
            printf("rtype=%d\n", data->rtype);
            printf("msgdata=%s\n", data->msgdata);
            printf("srcip=%s\n", data->srcip);
            printf("alarmtime=%ld\n", data->alarmtime);
    }

    return 1;
}

int add_stu(STUDENT *data)
{
    printf("rtype=%d\n", data->rtype);
    printf("msgdata=%s\n", data->msgdata);
    printf("srcip=%s\n", data->srcip);
    printf("alarmtime=%ld\n", data->alarmtime);
    return 1;
}

int add_data(STUDENT data)
{
    printf("rtype=%d\n", data.rtype);
    printf("msgdata=%s\n", data.msgdata);
    printf("srcip=%s\n", data.srcip);
    printf("alarmtime=%ld\n", data.alarmtime);
    return 1;
}

#if 0
int main()
{
    STUDENT st;
    memset((void*)&st, 0, sizeof(st));
    st.rtype = 1;
    st.alarmtime = time(NULL);
    strcpy(st.srcip , "xiaoqing");

    add_data(st);
    add_stu(&st);
}
#endif

頭文件1.h

#ifndef _1_H_
#define _1_H_

#include <time.h>
#if 0
typedef struct _tag_st{
    int age;
    char name[12];
    char color[12];
    time_t alarmtime;
    int hi;
}STUDENT;
#endif 
typedef enum{
    LK_ALARM_TYPE_IP = 1,
    LK_ALARM_TYPE_DOMAIN,
    LK_ALARM_TYPE_URL,
    LK_ALARM_TYPE_FHASH,
    LK_ALARM_TYPE_MAX
}ALARM_TYPE_E;
typedef struct tag_threat_rawdata{
    int rtype;             // 請求類型
    time_t alarmtime;               // 威脅事件發生時間
    char msgdata[128];              // 檢測信息

    char srcip[48];                 // 源IP
    char dstip[48];                 // 目的IP
    char trans_proto[8];            // 傳輸層協議
    char app_proto[16];             // 應用層協議
    short sport;                    // 源端口
    short dport;                    // 目的端口
    int flag;                       //元素讀、寫標誌,0-可寫,1-可讀
}STUDENT;

int add(int a, int b);
int add_stu(STUDENT *data);
int add_stus(STUDENT *data, int count);
int add_data(STUDENT data);
#endif

生成動態庫

$ gcc 1.c -fPIC -shared -o libmystu.so

注意:一定要用gcc編譯,python調用c/c++接口只支持gcc生成的動態庫

python 源碼

#!/usr/bin/python3.4
# -*- coding:utf-8 -*-

from ctypes import *
import time
import sys
import os

dll = cdll.LoadLibrary("./libmystu.so") #加載動態庫

LK_ALARM_TYPE_IP=1
LK_ALARM_TYPE_DOMAIN=2
LK_ALARM_TYPE_URL=3
LK_ALARM_TYPE_FHASH=4

#定義結構體
class ThreatClass(Structure):  
       _fields_ = [
            ("rtype", c_int),
            ("alarmtime", c_long),
            ("msgdata", c_char * 128),
            ("srcip", c_char * 48),
            ("dstip", c_char * 48),
            ("trans_proto", c_char * 8),
            ("app_proto", c_char * 16),
            ("sport", c_short),
            ("dport", c_short),
            ("flag", c_int)
      ]


def add_threat(array, count):
    try:
        if count <= 0:
            return 

        entrylist = []
        i = 0
        for data in array:
            threat = ThreatClass()
           
            threat.rtype = data["rtype"]
            threat.alarmtime = data["alarmtime"] 
            threat.msgdata = bytes(data["msgdata"].encode())
            threat.srcip = bytes(data["srcip"].encode())
            threat.dstip = bytes(data["dstip"].encode())
            threat.trans_proto = bytes(data["trans_proto"].encode())
            threat.app_proto = bytes(data["app_proto"].encode())
            threat.sport = data["sport"]
            threat.dport = data["dport"]
            threat.flag = 0

            #dll.add_stu.argtype = POINTER(ThreatClass)
            #dll.add_stu.restype = c_int
            #ret = dll.add_stu(byref(threat))
            #entrylist.append(threat)

            i = i+1

        #定義結構體數組,批量插入
        ThreatArray = (ThreatClass * i)(*entrylist)
        dll.add_stus.argtypes = (POINTER(ThreatClass), c_int) #指定C接口的參數類型,List格式
        dll.add_stus.restype = c_int  #指定C接口的返回值類型
        ret = dll.add_stus(ThreatArray, i)
        print(ret)
        
    except Exception as err:
        print(err)
        
if __name__ == '__main__':
    arrary = []
    data = {}
    data["alarmtime"] = int(time.time())
    data["msgdata"] = "1.1.1.56"
    data["srcip"] = "172.16.110.10"
    data["dstip"] = "172.16.110.11"
    data["trans_proto"] = "tcp"
    data["app_proto"] = "http"
    data["sport"] = 1204
    data["dport"] = 1205
    data["rtype"] = LK_ALARM_TYPE_IP
    arrary.append(data)

    da = {}
    da["alarmtime"] = int(time.time())
    da["msgdata"] = "9.9.9.9"
    da["srcip"] = "172.16.110.10"
    da["dstip"] = "172.16.110.11"
    da["trans_proto"] = "tcp"
    da["app_proto"] = "http"
    da["sport"] = 1204
    da["dport"] = 1205
    da["rtype"] = LK_ALARM_TYPE_IP
    arrary.append(da)

    add_threat(arrary, 2)    

注意:1. python 定義的結構體順序一定要與C定義的結構體順序一致

           2. python 定義的結構體中的數組元素的長度要與C結構體中的數組長度一致,保持對齊

           3. 字符數組要如此處理,bytes(data["srcip"].encode())再傳遞

           4. 結構體數組的定義要 ThreatArray = (ThreatClass * i)(*entrylist), entrylist是列表,存儲對象

           

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章