2017-11-03 6 views
1

나는 필사적으로 C 함수를 호출하는 래퍼를 작성하는 것을 시도하고있다 :는 C 함수로 다차원 배열을 전달 할 수 없음에 * .pyx

  • 입력
  • 으로 여러 다차원 C-연속 배열을을
  • 일부 작업을 수행하는 C 루틴의 배열을 사용하십시오.

내가 첨부 된 코드에서 나는 파이썬에서 액세스 할 수 있도록 노력하고 있습니다. 첫 번째 함수 SurfInfo은 C 함수 PosAndTgtSurfVec을 호출하며이 함수는 예상대로 작동합니다. 작동하게하려면 this tutorial을 사용했습니다. 문제는 C 함수 SurfToSurf을 호출하는 두 번째 래핑 함수 Surf2Surf에 있습니다. C 함수는 수정할 수 없습니다.

import cython 
cimport numpy as np 
import numpy as np 
from cython cimport view 
from cpython cimport array 

cdef extern void PosAndTgtSurfVec(double v[156],double X[18],double u[18] 
    ,double t1[3],double t2[3],double (*a),double (*b),double (*xi),double (*theta) 
    ,double s[3],double sxi[3],double stheta[3]) 

cdef extern void SurfToSurf(double v[5901],double X[2][12],double u[2][12] 
    ,double t1[2][3],double t2[2][3],double a[2],double b[2],double hFG[4] 
    ,double h[4],double R[24],double K[24][24]) 

# ---------------------------------------------------------# 
# This one works ! 
def SurfInfo(
     np.ndarray[np.double_t, ndim=1, mode="c"] X, 
     np.ndarray[np.double_t, ndim=1, mode="c"] u, 
     np.ndarray[np.double_t, ndim=1, mode="c"] t1, 
     np.ndarray[np.double_t, ndim=1, mode="c"] t2, 
     double a, 
     double b, 
     double xi, 
     double theta 
     ): 

    # declarations of pure C variables 
    # used for output 
    cdef : 
     double v[156]; 
     double s[3]; 
     double sxi[3]; 
     double stheta[3]; 

    PosAndTgtSurfVec(v, &X[0], &u[0], &t1[0], &t2[0], &a, &b, &xi, &theta, s, sxi, stheta) 
    return s, sxi, stheta 
# ---------------------------------------------------------# 


# ---------------------------------------------------------# 
# This one does not compile! 
def Surf2Surf(
    np.ndarray[double, ndim=2, mode="c"] X not None, 
    np.ndarray[double, ndim=2, mode="c"] u, 
    np.ndarray[double, ndim=2, mode="c"] t1, 
    np.ndarray[double, ndim=2, mode="c"] t2, 
    np.ndarray[double, ndim=1, mode="c"] a, 
    np.ndarray[double, ndim=1, mode="c"] b, 
    np.ndarray[double, ndim=1, mode="c"] hFG): 

    cdef double v[5901]; 
    cdef double h[4]; 
    cdef double R[24]; 
    cdef double K[24][24]; 

    SurfToSurf(v, &X[0,0], &u[0,0], &t1[0,0], &t2[0,0], &a[0], &b[0], &hFG[0],h, R,K) 
    return (h, R, K) 
# ---------------------------------------------------------# 

컴파일 오류는 다음과 같습니다 :

SurfToSurf(v, &X[0,0], &u[0,0], &t1[0,0], &t2[0,0], &a[0], &b[0], &hFG[0],h, R,K) 
       ^
------------------------------------------------------------ 

wrp.pyx:54:18: Cannot assign type 'double *' to 'double (*)[12]' 

내가 필요한 유형을 제공하려면 어떻게

코드는 다음과 같은 하나? 첫 번째 경우처럼 배열의 첫 번째 요소 주소를 제공하는 것이 효과적 일 것이라고 생각했습니다. 질문이 어리석은 경우 유감스럽게도 문제가 해결 될 수 있도록 도움을 줄 수있는 문서 또는 예제로 리디렉션 할 수 있다면 기뻤습니다. (이미 this linkthis book을 확인했는데 확실하게 답을 찾지 못했습니다.) 나는 아닙니다 당분간 공연을 찾고 있습니다.

+1

포인터가 1 차원 배열로 처리 될 수 있지만 2 차원 배열에서도 마찬가지입니다. 각 행을 인덱싱하기 위해 오프셋이 필요한 정도를 알기 위해 얼마나 많은 요소가 행에 있는지 알지 못합니다. 편집 : 나는 사람들이 일반적으로 여행 어디 다른 방법보다는 주위에 2 차원 배열로 포인터를 전달하려고하는 것을 참조하십시오. –

+0

@MacroMag 필자는 내 대답을 삭제했습니다. 함수가'double ** '을 사용하도록 정의되었지만 2D C 배열을 이해하지 못했던 것으로 밝혀졌습니다. 그래서 생각했던 것만 큼 적절하지 않습니다. 죄송합니다. 오해의 소지가 있습니다. 나는 두려운 정답을 모른다. – DavidW

+0

@MarcoMag 수정보기 -이 버전은 작동합니다 ... – DavidW

답변

2

두 번째 시도 ... (convertible to a pointer to a double[12]입니다)

2D C arrays like double[2][12] are apparently stored as an array of double[12]s. 따라서 실제로는 연속적으로 메모리에 저장되므로 C에서 연속적으로 배열 된 배열 (예 : 전달하는 배열)과 호환되어야합니다.

numpy 배열의 첫 번째 요소 인 double*double[12] r에 대한 포인터로 재 해석하는 데 필요한 작업 만 수행하면됩니다. (그들은 종종 논리 오류를 숨길 수 있기 때문에 캐스트 이상적 결코하지만이 경우 또 다른 옵션이 생각하지 않습니다) : 나는 당신의 arrays.Without의 크기를 확인하기에 assert을 추가 한

# I'm using this instead of `cdef extern` just to provide an easy way 
# of printing the elements and thus confirming that it works 
cdef void SurfToSurf(double[2][12] x): 
    for j in range(2): 
     for i in range(12): 

def Surf2Surf(np.ndarray[double, ndim=2, mode="c"] X): 
    assert X.shape[0]>=2 and X.shape[1]==12 

    SurfToSurf(<double (*)[12]>&X[0,0]) 
      print(x[j][i]) 

가 너무 작은 배열이 파이썬 인터페이스를 통과하면 프로그램이 다운 될 위험이 있습니다.