공유 라이브러리의 함수 포인터를 ctypes로 교체

U.Martinez-Corral

ctypes를 통해 공유 라이브러리의 기존 함수 포인터를 Python에 정의 된 콜백으로 바꾸려고합니다.

C에서 공유 라이브러리의 소스 :

#include <assert.h>
#include <stdio.h>

void (*plot)();

int c_main(int argc, void** argv) {
  printf("plot is %p\n", (void*)plot);
  assert(plot != NULL);
  plot();
  return 0;
}

Python 스크립트의 소스 :

from sys import platform
from pathlib import Path
import ctypes
import _ctypes


FUNCTYPE = ctypes.WINFUNCTYPE if platform == 'win32' else ctypes.CFUNCTYPE


def dlclose(obj):
    if platform == "win32":
        _ctypes.FreeLibrary(obj._handle)
    else:
        _ctypes.dlclose(obj._handle)


def enc_args(args):
    C_ARGS = (ctypes.POINTER(ctypes.c_char) * len(args))()
    for idx, arg in enumerate(args):
        C_ARGS[idx] = ctypes.create_string_buffer(arg.encode("utf-8"))
    return C_ARGS


@FUNCTYPE(None)
def plotxy():
    print("plotxy")


C_ARGS = enc_args([str(Path(__file__))])
CAUXDLL = ctypes.CDLL("./test.so")

print(plotxy)

print(CAUXDLL.plot)

CAUXDLL.plot = plotxy

print(CAUXDLL.plot)

print(CAUXDLL.c_main(len(C_ARGS), C_ARGS))

테스트 할 스크립트 :

gcc -fPIC -shared -o test.so test.c
python3 test.py

내가 얻는 출력 :

# ./test.sh
<CFunctionType object at 0x7fb1f0abb1c0>
<_FuncPtr object at 0x7fb1f0abb640>
<CFunctionType object at 0x7fb1f0abb1c0>
plot is (nil)
python3: test.c:8: c_main: Assertion `plot != NULL' failed.
./test.sh: line 3: 21171 Aborted                 python3 test.py

따라서 Python (plotxy)에서 정의 된 함수는 type CFunctionType이고 C로 정의 된 함수 포인터 는 type 것으로 보입니다 _FuncPtr. 대체 CAUXDLL가 적용 되어 있지만 주 함수가 호출되면 효과가없는 것 같습니다.

https://docs.python.org/3/library/ctypes.html#module-ctypes 를 읽는 것 외에도 다른 질문을 발견했습니다 (예 : ctypes에서 typedef를 사용하는 방법 또는 콜백 함수를 만드는 파이썬 cytpes-세분화 오류 (코어 덤프)) ),하지만 CFunctionType(plotxy)를 _FuncPtr.

편집하다

나는 이것이 ctypes의 일반적인 사용에 문제가되지 않을 것이라고 생각합니다. 그것은 내가 성공적으로 성취 한 것이며 문서에 충분히 설명되어 있습니다. 이 질문은 그 이상입니다. C 함수를 실행하고 싶지 않습니다. Python으로 기존 함수 포인터를 Python으로 작성된 콜백으로 바꾸고 싶습니다. 도우미 C 함수를 사용하여 수행 할 수 있습니다 ( https://github.com/ghdl/ghdl-cosim/blob/master/vhpidirect/shared/pycb/caux.c#L32-L40 참조 ). 따라서이 질문은 (가능한 경우) 도우미 기능없이이를 달성하는 방법에 관한 것입니다.

마크 톨로 넨

에서 전역 변수에 액세스하는 방법은를 ctypes사용하는 in_dll것이지만 함수 포인터를 변경하는 노출 된 방법은없는 것 같습니다. 나는 그것을 읽고 호출 할 수 밖에 없었기 때문에 도우미 기능 없이는 불가능하다고 생각합니다.

아래 예제는 int전역 변수를 변경 하지만 CFUNCTYPE인스턴스에는이 value를 변경할 멤버 가 없습니다 . 문제를 해결하기 위해 전역을 설정하는 C 도우미를 추가하고 변경하기 전에 올바르게 액세스되었는지 확인하기 위해 콜백의 기본값을 추가했습니다.

test.c :

#include <stdio.h>

#define API __declspec(dllexport)

typedef void (*CB)();

void dllplot() {
    printf("default\n");
}

API CB plot = dllplot;
API int x = 5;

API int c_main() {
  printf("x=%d (from C)\n",x);
  plot();
  return 0;
}

API void set_cb(CB cb) {
    plot = cb;
}

test.py :

from ctypes import *

PLOT = CFUNCTYPE(None)

dll = CDLL('./test')
dll.c_main.argtypes = ()
dll.c_main.restype = c_int
dll.set_cb.argtypes = PLOT,
dll.set_cb.restype = None

@PLOT
def plotxy():
    print("plotxy")

x = c_int.in_dll(dll,'x')
plot = PLOT.in_dll(dll,'plot')
print(f'x={x.value} (from Python)')
x.value = 7
print('calling plot from Python directly:')
plot()
print('calling c_main():')
dll.c_main()
dll.set_cb(plotxy)
print('calling plot from Python after setting callback:')
plot()
print('calling plot from C after setting callback:')
dll.c_main()

산출:

x=5 (from Python)
calling plot from Python directly:
default
calling c_main():
x=7 (from C)
default
calling plot from Python after setting callback:
plotxy
calling plot from C after setting callback:
x=7 (from C)
plotxy

전역 포인터 .contents는 값에 액세스하는 데 사용 되므로 a POINTER(CFUNCTYPE(None))및 using 을 사용하여 실험 plot.contents = plotxy했지만 전역 변수를 올바르게 할당하지 않고 C가 충돌했습니다.

함수 포인터에 실제 전역 포인터를 추가하려고 시도했습니다.

API CB plot = dllplot;
API CB* pplot = &plot;

그리고 다음을 사용합니다.

PLOT = CFUNCTYPE(None)
PPLOT = POINTER(PLOT)
plot = PPLOT.in_dll(dll,'pplot')
plot.contents = plotxy

을 통해 함수를 할당 할 수 .contents있었지만 c_main여전히 기본 플롯 값이라고합니다. 따라서 CFUNCTYPE함수 매개 변수 이외의 다른 용도 로 사용하는 기능은 구현되지 않은 것으로 보입니다.

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

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

에서 수정
0

몇 마디 만하겠습니다

0리뷰
로그인참여 후 검토

관련 기사

분류에서Dev

C ++의 여러 인수를 MatLab 공유 라이브러리 함수에 전달

분류에서Dev

java 라이브러리의 패키지를 storm으로 교체

분류에서Dev

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

분류에서Dev

공유 라이브러리 플러그인 및 메인 프로그램 (Bluez)에서 함수 호출

분류에서Dev

operator <<를 제공하는 객체를 std :: string으로 변환하는 표준 라이브러리 함수

분류에서Dev

객체를 공유하기위한 창에서 공유 메모리 (포인터 인 멤버 포함)

분류에서Dev

공유 객체 라이브러리에 중단 점 x를 삽입 할 수 없습니다 (python은 C ++에서 .so 라이브러리를 사용함).

분류에서Dev

파이썬에서 공유 객체의 ctypes 함수로 구조체를 전달하는 방법은 무엇입니까?

분류에서Dev

petalinux의 공유 사전 빌드 라이브러리를 포함한 오류

분류에서Dev

CMake 프로젝트가 공유 라이브러리를 찾지 못함

분류에서Dev

타사 공유 라이브러리를 Python ctypes와 통합

분류에서Dev

로드 경로에 공급 업체 라이브러리를 포함하는 방법은 무엇입니까?

분류에서Dev

ctypes는 라이브러리로드를 소유하지만 함수 / 메소드에 액세스 할 수 없습니다.

분류에서Dev

3 개의 u32 포인터를 인수로 원하는 c 함수에 배열 및 구조체를 전달하는 방법 (ctypes)

분류에서Dev

공유 포인터 개체를 SWIG로 래핑하면 클래스 멤버 함수에 대한 액세스 권한이 부여되지 않습니다.

분류에서Dev

C ++-17 : 함수 포인터를 다른 인수 포인터 유형의 함수로 캐스팅

분류에서Dev

Jenkins 파일의 환경 변수를 코드로 파이프 라인이있는 공유 라이브러리로 전달

분류에서Dev

함수 포인터를 API 인터페이스로 컴파일 된 라이브러리에 전달

분류에서Dev

Symfony 2-Composer를 사용하여 패키지로 사용할 수없는 공급 업체 라이브러리 포함

분류에서Dev

다른 공유 라이브러리의 심볼도 포함되도록 공유 라이브러리 (.so)를 구축하려면 어떻게해야합니까?

분류에서Dev

pypy 라이브러리를로드 할 수 없음 : libpypy-c.so : 공유 객체 파일을 열 수 없음 : 해당 파일 또는 디렉토리 없음

분류에서Dev

tomcat 재정의 logging.properties는 공유 라이브러리에 포함

분류에서Dev

Python ctypes에서 공유 라이브러리를로드하는 동안 분할 오류 (코어 덤프)

분류에서Dev

ctypes-다른 라이브러리 호출에서 생성 된 구조체를 전달하는 라이브러리 함수 호출

분류에서Dev

mysql 커넥터로 공유 객체 라이브러리 (* .so)를 만드는 방법은 무엇입니까?

분류에서Dev

OpenGL 로더 함수 포인터를 #define해야하는 이유

분류에서Dev

라이브러리간에 C ++의 개체를 공유하는 방법

분류에서Dev

여러 플랫폼에서 포함 된 공유 라이브러리로 NDK 빌드

분류에서Dev

Visual C ++ 크로스 플랫폼 android : 미리 빌드 된 공유 라이브러리 포함

Related 관련 기사

  1. 1

    C ++의 여러 인수를 MatLab 공유 라이브러리 함수에 전달

  2. 2

    java 라이브러리의 패키지를 storm으로 교체

  3. 3

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

  4. 4

    공유 라이브러리 플러그인 및 메인 프로그램 (Bluez)에서 함수 호출

  5. 5

    operator <<를 제공하는 객체를 std :: string으로 변환하는 표준 라이브러리 함수

  6. 6

    객체를 공유하기위한 창에서 공유 메모리 (포인터 인 멤버 포함)

  7. 7

    공유 객체 라이브러리에 중단 점 x를 삽입 할 수 없습니다 (python은 C ++에서 .so 라이브러리를 사용함).

  8. 8

    파이썬에서 공유 객체의 ctypes 함수로 구조체를 전달하는 방법은 무엇입니까?

  9. 9

    petalinux의 공유 사전 빌드 라이브러리를 포함한 오류

  10. 10

    CMake 프로젝트가 공유 라이브러리를 찾지 못함

  11. 11

    타사 공유 라이브러리를 Python ctypes와 통합

  12. 12

    로드 경로에 공급 업체 라이브러리를 포함하는 방법은 무엇입니까?

  13. 13

    ctypes는 라이브러리로드를 소유하지만 함수 / 메소드에 액세스 할 수 없습니다.

  14. 14

    3 개의 u32 포인터를 인수로 원하는 c 함수에 배열 및 구조체를 전달하는 방법 (ctypes)

  15. 15

    공유 포인터 개체를 SWIG로 래핑하면 클래스 멤버 함수에 대한 액세스 권한이 부여되지 않습니다.

  16. 16

    C ++-17 : 함수 포인터를 다른 인수 포인터 유형의 함수로 캐스팅

  17. 17

    Jenkins 파일의 환경 변수를 코드로 파이프 라인이있는 공유 라이브러리로 전달

  18. 18

    함수 포인터를 API 인터페이스로 컴파일 된 라이브러리에 전달

  19. 19

    Symfony 2-Composer를 사용하여 패키지로 사용할 수없는 공급 업체 라이브러리 포함

  20. 20

    다른 공유 라이브러리의 심볼도 포함되도록 공유 라이브러리 (.so)를 구축하려면 어떻게해야합니까?

  21. 21

    pypy 라이브러리를로드 할 수 없음 : libpypy-c.so : 공유 객체 파일을 열 수 없음 : 해당 파일 또는 디렉토리 없음

  22. 22

    tomcat 재정의 logging.properties는 공유 라이브러리에 포함

  23. 23

    Python ctypes에서 공유 라이브러리를로드하는 동안 분할 오류 (코어 덤프)

  24. 24

    ctypes-다른 라이브러리 호출에서 생성 된 구조체를 전달하는 라이브러리 함수 호출

  25. 25

    mysql 커넥터로 공유 객체 라이브러리 (* .so)를 만드는 방법은 무엇입니까?

  26. 26

    OpenGL 로더 함수 포인터를 #define해야하는 이유

  27. 27

    라이브러리간에 C ++의 개체를 공유하는 방법

  28. 28

    여러 플랫폼에서 포함 된 공유 라이브러리로 NDK 빌드

  29. 29

    Visual C ++ 크로스 플랫폼 android : 미리 빌드 된 공유 라이브러리 포함

뜨겁다태그

보관