python 과 C 언어 를 혼합 하여 만 드 는 몇 가지 방식(추천)

Python 은 최근 몇 년 동안 인기 가 많아 서 많은 분야 의 위 치 를 차지 했다.웹,빅 데이터,인공지능,운영 은 모두 그의 모습 을 가지 고 심지어 도형 인터페이스 도 잘 만 들 었 다.심지어 full-stack 이라는 단어 가 처음 나 왔 을 때 이 를 묘사 하기 위 한 것 같 았 다.
Python 은 GIL 문제 로 인해 다 중 스 레 드 가 다 중 핵 을 충분히 이용 하지 못 했 지만 나중에 multiprocess 는 다 중 프로 세 스 의 측면 에서 다 중 핵 을 이용 할 수 있 고 심지어 affinity 는 구체 적 인 CPU 핵 을 연결 할 수 있 으 며 이 문제 도 해결 한 셈 이다.기본적으로 스 택 언어 이지 만 효율 성 을 위해 C 언어 와 의 혼합 을 고려 할 때 도 있다.혼합 편성 은 컴퓨터 에서 피 할 수 없 는 화제 로 관련 된 것 이 매우 많다.기술,구조,단체 상황,관리,고객 등 각 부분 이 모두 이에 영향 을 미 칠 수 있다.혼합 편성 이라는 문 제 는 내 가 생각 할 때 다시 전문 적 인 토론 을 하고 싶다.본 고 는 python 과 C 를 혼합 하 는 방식 만 말 하고 대체적으로 다음 과 같은 몇 가지 방식 이 있다(본 고의 배경 은 linux 이 고 다른 플랫폼 은 비교 할 수 있다).
공유 라 이브 러 리
C 언어 컴 파일 을 사용 하여 공유 라 이브 러 리 를 만 든 다음 python 은 ctype 라 이브 러 리 의 cdll 을 사용 하여 공유 라 이브 러 리 를 엽 니 다.
예 를 들 어 다음 과 같다.C 언어 코드 는?

/* func.c */int func(int a)
{
 return a*a;
} 
python 코드

#!/usr/bin/env python
#test_so.pyfrom ctypes import cdll
import os

p = os.getcwd() + '/libfunc.so'
f = cdll.LoadLibrary(p)
print f.func(99)  

테스트 는 다음 과 같다.

$ gcc -fPIC -shared func.c -o libfunc.so 
$ ./test_so.py 
9801

subprocess
C 언어 는 실행 가능 한 완전한 파일 을 설계 한 다음 에 python 은 subprocess 를 통 해 실행 가능 한 파일 을 실행 합 니 다.본질 적 으로 fork+execve 입 니 다.
예 를 들 어 다음 과 같다.C 언어 코드 는?

/* test.c */
#include <stdio.h>
int func(int a)
{
 return a*a;
}

int main(int argc, char **argv)
{
 int x;

 sscanf(argv[1], "%d", &x);
 printf("%d
", func(x)); return 0; }
Python 코드
#!/usr/bin/env python
# test_subprocess.py
import os
import subprocess
subprocess.call([os.getcwd()+'/a.out', '99'])  
테스트 는 다음 과 같다.
$ gcc test.c -o a.out
$ ./test_subprocess.py
9801
  
C 언어 에서 python 프로그램 실행
C 언어 는 popen/system 을 사용 하거나 시스템 호출 급 fork+exec 로 python 프로그램 을 직접 실행 하 는 것 도 혼합 편성 수단 이다.
예 를 들 어 다음 과 같 습 니 다.Python 코드 는 다음 과 같 습 니 다.

#!/usr/bin/env python
# test.py
import sys
x = int(sys.argv[1])
print x*x  

C 언어 코드 는 다음 과 같 습 니 다.

/* test.c */
#include <stdio.h>
#include <stdlib.h>
int main()
{
 FILE *f;
 char s[1024];
 int ret;

 f = popen("./test.py 99", "r");
 while((ret=fread(s,1,1024,f))>0) {
  fwrite(s,1,ret,stdout);
 }
 fclose(f);
 return 0;
}
테스트 는 다음 과 같다.

$ gcc test.c 
$ ./a.out
9801 
python 의 C 언어 확장 지원
많은 프로 그래 밍 언어 가 C 언어 확장 에 지원 을 추 가 했 습 니 다.이것 은 두 가지 이유 가 있 습 니 다.(1)언어 디자인 초기 에 C 언어 가 있 는 라 이브 러 리 를 충분히 이용 하여 많은 확장 을 할 수 있 었 습 니 다.(2)C 언어의 운행 효율 이 높다.
python 도 예 외 는 아니다.태 어 난 날 부터 많은 라 이브 러 리 는 C 언어 로 쓰 여 있다.python 의 C 언어 확장 에는 python 의 데이터 구조 와 C 언어의 대응 이 포함 되 어 있 습 니 다.확장 방법 은 C 언어 로 공유 라 이브 러 리 를 만 드 는 것 입 니 다.다만 이 공유 라 이브 러 리 의 인 터 페 이 스 는 규범 적 이 고 python 에 의 해 식별 할 수 있 습 니 다.
확장 방법 을 설명 하기 위해 서 저 는 먼저 python 에서 의 함수 기능 을 가정 합 니 다.코드 는 다음 과 같 습 니 다.

def func(*a):
 res=1
 for i in range(len(a)):
 res *= sum(a[i])
 return res
위 와 같이 원 하 는 함수 기능 은 매개 변 수 는 여러 개의 숫자 로 구 성 된 목록(다른 데이터 구 조 를 제외 하고)으로 각 목록 의 요소 의 합 을 되 돌려 주 는 것 입 니 다.
우선 python 코드 를 썼 습 니 다.아래 와 같 습 니 다.

#!/usr/bin/env python
# test.py
import colin

def func(*a):
 res=1
 for i in range(len(a)):
 res *= sum(a[i])
 return res

a = [1,2,3]
b = [4,5,6]
c = [7,8]
d = [9]
e = [10,11,12,13,14]

f = colin.func2(99)
g = colin.func3(a,b,c,d,e)
h = func3(a,b,c,d,e)
print "f = ",f
print "g = ",g
print "h = ",h
이전에 테스트 해 왔 던 제곱 func 를 가 져 옵 니 다.이것 은 상대 적 으로 간단 합 니 다.python 이 쓴 func 가 C 언어 로 확 장 된 결과 와 일치 하 기 를 바 랍 니 다.
먼저 C 언어 로 이 함수 들 의 실현 을 적 었 습 니 다.그 중에서 func 3 는 임의의 긴 배열 을 나타 내 는 데이터 구조 y 를 사 용 했 습 니 다.t,그리고 xt 는 하나의 배열 을 나타 내 는 데 쓰 인 다.

/* colin.h */
#ifndef Colin_h
#define Colin_h
typedef struct {
 int *a;
 int len;
} x_t;
typedef struct {
 x_t *ax;
 int len;
} y_t;
int func2(int a);
int func3(y_t *p);
void free_y_t(y_t *p);
#endif

/* colin.c */
#include "colin.h"
#include <stdlib.h>

int func2(int a)
{
 return a*a;
}

int func3(y_t *p)
{
 int result;
 int sum;
 int i, j;

 result = 1;
 for(i=0;i<p->len;i++) {
  sum = 0;
  for(j=0;j<p->ax[i].len;j++)
   sum += p->ax[i].a[j];
  result *= sum;
 }

 return result;
}

void free_y_t(y_t *p)
{
 int i;
 for(i=0;i<p->len;i++) {
  free(p->ax[i].a);
 }
 free(p->ax);
}
위 에서 세 개의 함 수 를 정 의 했 는데 func 2 는 제곱 을 대표 하고 func 3 는 앞에서 말 한 기능 을 대표 하 며 또 yt.이 구 조 는 모두 동적 으로 분 배 될 수 있 기 때문에 메모리 반환 방법 을 줍 니 다.
방금 python 확장 이 라 고 했 으 니 이 공유 라 이브 러 리 의 인 터 페 이 스 를 표준화 해 야 합 니 다.그래서 우 리 는 포장 을 해서 python 에 불 러 오 는 입 구 를 주 었 다.

/* wrap.c */
#include <Python.h>
#include <stdlib.h>
#include "colin.h"
PyObject* wrap_func2(PyObject* self, PyObject* args)
{
 int n, result;
 /*             , "i" */
 if (!PyArg_ParseTuple(args, "i", &n))
  return NULL;

 /*  C          */
 result = func2(n);
 /*          python      */
 return Py_BuildValue("i", result);
}

PyObject* wrap_func3(PyObject* self, PyObject* args)
{
 int n, result;
 int i, j;
 int size, size2;
 PyObject *p,*q;
 y_t *y;

 y = malloc(sizeof(y_t));
 /*          ,         */
 size = PyTuple_Size(args);
 /*            */
 y->len = size;
 y->ax = malloc(sizeof(x_t)*size);
 /*   python     (  ) */
 for(i=0;i<size;i++) {
  /*     i   ,      */
  p = PyTuple_GetItem(args, i);
  /*         */
  size2 = PyList_Size(p);
  /*          */
  y->ax[i].len = size2;
  y->ax[i].a = malloc(sizeof(int)*size2);
  /*     ,              */
  for(j=0;j<size2;j++) {
   q = PyList_GetItem(p, j);
   PyArg_Parse(q,"i",&y->ax[i].a[j]);
  }
 }

 /*  C          */
 result = func3(y);
 free_y_t(y);
 free(y);
 /*     python     */
 return Py_BuildValue("i", result);
}

/*       ,             ,            (    ) ,     */
static PyMethodDef colinMethods[] =
{
 {"func2", wrap_func2, METH_VARARGS, "Just a test"},
 {"func3", wrap_func3, METH_VARARGS, "Just a test"},
 {NULL, NULL, METH_NOARGS, NULL}
};

/* python         */
/*   ,     colin,      initcolin */
void initcolin()
{
 PyObject *m;
 m = Py_InitModule("colin", colinMethods);
}
그 과정 에서 PyArgVaParse 는 기능 이 더욱 강해 야 하 는데 반복 적 으로 테스트 가 성공 하지 못 했 고 문 서 를 자세히 보지 못 했다.
테스트 해 봐.

$ gcc -I /usr/include/python2.7/ -fPIC -shared colin.c wrap.c -o colin.so 
$ ./test.py 
f = 9801 
g = 729000 
h = 729000 

C 언어 가 쓴 함수 와 python 이 쓴 함수 결과 가 일치 하 는 것 을 볼 수 있 습 니 다.
이상 의 이 평론 python 과 C 언어 를 혼합 한 몇 가지 방식(추천)은 바로 편집장 이 여러분 에 게 공유 한 모든 내용 입 니 다.여러분 에 게 참고 가 될 수 있 고 많은 응원 을 바 랍 니 다.

좋은 웹페이지 즐겨찾기