Fortran 파생 형식 내부의 C 함수에 대한 포인터 보유

Eos Pengwern

C 프로그램에서 호출되는 Fortran DLL이 있으며 내 프로 시저 중 하나는 C 프로그램에서 제공하는 콜백 함수를 주기적으로 호출해야합니다. 현재 '간단한'형태로 잘 작동하지만 파생 된 형식 내에 콜백 포인터를 저장하여 Fortran 코드 내에서 더 쉽게 전달할 수 있기를 원합니다. 지금까지 내가 시도한 것은 작동하지 않는 것 같습니다.

여기로 시작하는 것은 내가 지금 가지고 있고, 이것이 무엇을 수행 작업 :

C (OK, 실제로는 C ++) 프로그램에서 시작하여 콜백의 헤더 프로토 타입은 다음과 같습니다.

typedef void (*fcb)(void *)

Fortran 호출의 프로토 타입은 다음과 같습니다.

extern "C" __declspec(dllexport) int fortran_function(int n,
                                                      uchar *image_buffer,
                                                      fcb callback,
                                                      void *object);

실제 콜백 함수는 다음과 같습니다.

void callback(void* pObject)
{
    // Cast the void pointer back to the appropriate class type:
    MyClass *pMyObject = static_cast<MyClass *>(pObject);
    pMyObject -> updateImageInGUI();
}

C ++에서 Fortran 코드에 대한 호출은 다음과 같습니다.

int error = fortran_function(m_image.size(), m_image.data, callback, this);

여기서는 m_image현재 객체의 멤버 속성 인 이미지 데이터의 배열입니다. C ++는 원시 이미지 데이터를 Fortran DLL에 전달하고 Fortran에 처리하도록 요청합니다. 이렇게하면 시간이 오래 걸리기 때문에 Fortran은 주기적으로 이미지 버퍼를 업데이트하고 콜백을 호출하여 GUI를 새로 고칩니다. 어쨌든 Fortran 측으로 이동하여 C 콜백에 대한 인터페이스를 정의합니다.

abstract interface
    subroutine c_callback(c_object) bind(c)   
        use, intrinsic :: iso_c_binding
        type(c_ptr), intent(in) :: c_object     
    end subroutine c_callback
end interface

다음과 같이 주요 Fortran 루틴을 정의합니다.

integer(c_int) fortran_function(n, image, callback, c_object)     &
                                bind(c, name='fortran_function')

    integer(c_int), value :: n
    integer(4), intent(inout), dimension(n) :: image
    procedure(c_callback) :: callback
    type(c_ptr), intent(in) :: c_object

메인 루틴 어딘가에서 우리는 서브 루틴이라고 부릅니다 foo.

call foo(data, callback, c_object)

... 여기서는 foo다음과 같이 정의됩니다.

subroutine foo(data, callback, c_object)

    type(my_type), intent(inout) :: data
    procedure(c_callback) :: callback
    type(c_ptr), intent(in) :: c_object
    ...
    call callback(c_object)
    ...
end function foo

내가 말했듯이,이 모든 것이 잘 작동하며 오랫동안 그렇게 해왔습니다.

이제 내가 시도했지만 작동하지 않는 것들에 대해 :

구조의 필드에 인수를 복사하는 순진한 접근 방식

내가하는 일은 수정없이 원래 요소를 구조에 복사하는 것뿐이므로 이것이 작동 할 것으로 기대합니다. C 측에서는 아무것도 변경되지 않으며, 주요 Fortran 기능의 정의 나 c_callback. 내가 할 일은 새로운 Fortran 파생 유형을 만드는 것입니다.

type :: callback_data
    procedure(c_callback), pointer, nopass :: callback => null()
    type(c_ptr) :: c_object
end type callback_data

그런 다음 내 주요 기능에서 C 응용 프로그램에서받은 값으로 이것을 채 웁니다.

data%callback_data%callback => callback
data%callback_data%c_object = c_object
call foo(data)

서브 루틴 foo가 약간 수정되어 이제 구조 내에서 콜백 및 C 객체를 찾습니다.

subroutine foo(data)
    type(my_augmented_type), intent(inout) :: data
    ...
    call data%callback_data%callback(data%callback_data%c_object)
    ...
end function foo

이것은 "0xffffffffffffffff 위치를 읽는 액세스 위반"으로 호출에서 실패합니다.

더 많은 iso_c_binding 기능을 사용하는 정교한 접근 방식

다시 C 측에서는 아무것도 변경되지 않지만 주 함수의 Fortran 측을 수정하여 콜백을 다음과 같이 수신합니다 c_funptr.

integer(c_int) fortran_function(n, image, callback, c_object)     &
                                bind(c, name='fortran_function')

    integer(c_int), value :: n
    integer(4), intent(inout), dimension(n) :: image
    type(c_funptr), intent(in) :: callback
    type(c_ptr), intent(in) :: c_object

추상 인터페이스를 subroutine c_callback이전과 똑같이 정의 했지만, bind(c)일부 를 그대로두고 생략하는 두 가지를 모두 실험 했습니다. 서브 루틴을 호출하는 주 함수 내의 코드 foo는 다음과 같습니다.

call c_f_procpointer(callback, data%callback_data%callback)
data%callback_data%c_object = c_object
call foo(data)

... 서브 루틴 foo 자체가 이전 예제에서와 같이 여전히 정의되어 있습니다.

불행히도 이것은 이전 예제와 똑같은 방식으로 실패합니다.

여기서 달성하고자하는 것을 달성하기위한 올바른 구문이 있다고 가정하고 조언에 대해 매우 감사하겠습니다.

IanH

BIND(C)VALUE 인수가없는 속성을 가진 Fortran 프로 시저의 더미 인수 는 C 측에서 포인터 매개 변수와 동일합니다 (이것은 참조로 전달되는 일반적인 Fortran 규칙과 대체로 일치합니다). 따라서 Fortran 측에 INTEGER(C_INT) :: a(값 속성 없음)이 있으면 C 측에서 int *a.

아마도 분명하지만 놀라운 결과를 가지 - 당신이있는 경우에 TYPE(C_PTR) :: p, 그와 동등의 void **p- C_PTR가 포인터하는 C_PTR이 값이 포인터에 대한 포인터없이 통과되도록. 이것이 주어지면 콜백에 대한 인터페이스가 나옵니다 (를 추가해야 함 VALUE).

Fortran에서 함수에 대한 C 포인터에 대한 유형 의미에서 상호 운용 가능한 아날로그는 TYPE(C_FUNPTR). VALUE 속성 및 C_PTR적용 의 부재와 관련하여 동일한 고려 사항이 있습니다. 선언 된 인수는 TYPE(C_FUNPTR) :: f함수에 대한 포인터에 대한 포인터입니다. 이것과 Fortran의 C 측 호출이 주어지면 함수 포인터에 해당하는 인수에는 VALUE속성 이 있어야 합니다.

Fortran 프로 시저 포인터가 작동한다는 사실은 C 함수 포인터 및 Fortran 프로 시저 포인터의 기본 구현과 Fortran 프로 시저 포인터가 전달되는 방식의 우연한 일치 일뿐입니다.

전체적으로 Fortran 절차에는 다음과 같은 인터페이스가 있어야합니다.

integer(c_int) fortran_function(n, image, callback, c_object)     &
                                bind(c, name='fortran_function')

  integer(c_int), value :: n
  integer(c_signed_char), intent(inout), dimension(n) :: image
  type(c_funptr), intent(in), value :: callback
  type(c_ptr), intent(in), value :: c_object

(원래 코드에서 이미지 배열에 대한 선언이 잘못된 것 같습니다. 아마도 위의 내용은 적절하지 않을 수도 있습니다)

C 콜백의 인터페이스 선언에는 다음과 같은 인터페이스가 있어야합니다.

abstract interface
  subroutine c_callback(c_object) bind(c)   
    use, intrinsic :: iso_c_binding
    implicit none
    type(c_ptr), intent(in), value :: c_object     
  end subroutine c_callback
end interface

(마찬가지로 당신이되었습니다 지난 몇 개월 동안 인텔 포럼 (논의?), 현재 ifort 그것의 취급있어에 문제가있을 수 있습니다 C_PTRVALUE.)

이 기사는 인터넷에서 수집됩니다. 재 인쇄 할 때 출처를 알려주십시오.

침해가 발생한 경우 연락 주시기 바랍니다[email protected] 삭제

에서 수정
0

몇 마디 만하겠습니다

0리뷰
로그인참여 후 검토

관련 기사

분류에서Dev

Fortran 파생 형식의 멤버 변수 인 배열에 대한 포인터

분류에서Dev

Fortran 유형에 대한 하나의 포인터

분류에서Dev

Fortran 2003, 부모 유형의 인수에 파생 유형 전달

분류에서Dev

함수의 벡터 벡터에 대한 포인터 '표현식에 포인터 유형이 있어야 함'오류가 발생 함

분류에서Dev

C ++ : 인수 유형이 다른 함수에 대한 함수 포인터 벡터

분류에서Dev

여러 유형의 함수에 대한 매개 변수로 함수 포인터를받는 함수에 대한 템플릿 함수 생성

분류에서Dev

C ++ 내부의 C 함수에 대한 포인터에 대한 Typedef

분류에서Dev

C ++의 함수에 대한 포인터

분류에서Dev

friend 함수의 기본 클래스 인수 유형에 대한 포인터

분류에서Dev

일부 기본 데이터 유형에 대한 포인터의 형변환 (내부적으로 발생하는 일)

분류에서Dev

클래스에 대한 포인터 대 내장 유형에 대한 포인터

분류에서Dev

ctypes를 사용하여 유형 포인터의 매개 변수를 C 함수에 대한 포인터로 전달

분류에서Dev

MPI 창에 대한 기준 포인터로 파생 된 데이터 유형

분류에서Dev

상수 변수에 대한 C ++ 유형 캐스팅 포인터

분류에서Dev

확장의 정적 함수에 대한 유형 파생

분류에서Dev

자식 클래스 생성자의 인터페이스 클래스 함수에 대한 함수 포인터

분류에서Dev

배열에 대한 C ++ 포인터 오류 : 단항 *의 유효하지 않은 유형 인수 ( 'int 포함), 할당의 왼쪽 피연산자로 lvalue 필요

분류에서Dev

C의 불완전한 유형 큐에 대한 역 참조 포인터

분류에서Dev

올바른 크기를 제공하지 않는 함수 내부 포인터에 대한 포인터의 C malloc

분류에서Dev

C Re : Void 및 문자 유형에 대한 포인터, Typecasting 보장

분류에서Dev

포인터 일 때 함수의 반환 유형에 대한 혼란

분류에서Dev

float C 배열에 대한 공용체 유형 (구조체도 포함)의 포인터

분류에서Dev

부동 소수점 숫자에 대한 Fortran 형식의 출력

분류에서Dev

구조 유형에 대한 포인터에서 파생 된 모든 포인터가 동일합니까?

분류에서Dev

C ++ : 기본 형식 포인터에서 파생 된 형식 확인

분류에서Dev

구조 내부의 요소에 대한 포인터 (C)

분류에서Dev

C의 구조체 유형에 대한 포인터 캐스팅 이해

분류에서Dev

불완전한 유형 C에 대한 역 참조 포인터

분류에서Dev

qsort ()의 비교 함수에서 구조체의 값 사용-C99-불완전한 유형에 대한 포인터 역 참조

Related 관련 기사

  1. 1

    Fortran 파생 형식의 멤버 변수 인 배열에 대한 포인터

  2. 2

    Fortran 유형에 대한 하나의 포인터

  3. 3

    Fortran 2003, 부모 유형의 인수에 파생 유형 전달

  4. 4

    함수의 벡터 벡터에 대한 포인터 '표현식에 포인터 유형이 있어야 함'오류가 발생 함

  5. 5

    C ++ : 인수 유형이 다른 함수에 대한 함수 포인터 벡터

  6. 6

    여러 유형의 함수에 대한 매개 변수로 함수 포인터를받는 함수에 대한 템플릿 함수 생성

  7. 7

    C ++ 내부의 C 함수에 대한 포인터에 대한 Typedef

  8. 8

    C ++의 함수에 대한 포인터

  9. 9

    friend 함수의 기본 클래스 인수 유형에 대한 포인터

  10. 10

    일부 기본 데이터 유형에 대한 포인터의 형변환 (내부적으로 발생하는 일)

  11. 11

    클래스에 대한 포인터 대 내장 유형에 대한 포인터

  12. 12

    ctypes를 사용하여 유형 포인터의 매개 변수를 C 함수에 대한 포인터로 전달

  13. 13

    MPI 창에 대한 기준 포인터로 파생 된 데이터 유형

  14. 14

    상수 변수에 대한 C ++ 유형 캐스팅 포인터

  15. 15

    확장의 정적 함수에 대한 유형 파생

  16. 16

    자식 클래스 생성자의 인터페이스 클래스 함수에 대한 함수 포인터

  17. 17

    배열에 대한 C ++ 포인터 오류 : 단항 *의 유효하지 않은 유형 인수 ( 'int 포함), 할당의 왼쪽 피연산자로 lvalue 필요

  18. 18

    C의 불완전한 유형 큐에 대한 역 참조 포인터

  19. 19

    올바른 크기를 제공하지 않는 함수 내부 포인터에 대한 포인터의 C malloc

  20. 20

    C Re : Void 및 문자 유형에 대한 포인터, Typecasting 보장

  21. 21

    포인터 일 때 함수의 반환 유형에 대한 혼란

  22. 22

    float C 배열에 대한 공용체 유형 (구조체도 포함)의 포인터

  23. 23

    부동 소수점 숫자에 대한 Fortran 형식의 출력

  24. 24

    구조 유형에 대한 포인터에서 파생 된 모든 포인터가 동일합니까?

  25. 25

    C ++ : 기본 형식 포인터에서 파생 된 형식 확인

  26. 26

    구조 내부의 요소에 대한 포인터 (C)

  27. 27

    C의 구조체 유형에 대한 포인터 캐스팅 이해

  28. 28

    불완전한 유형 C에 대한 역 참조 포인터

  29. 29

    qsort ()의 비교 함수에서 구조체의 값 사용-C99-불완전한 유형에 대한 포인터 역 참조

뜨겁다태그

보관