홈으로 돌아가기

GLFW를 통한 PHP FFI의 OpenGL 확장

이 글은 외부 DLL 없이 GLFW를 통해 PHP FFI에서 OpenGL 확장을 구현하는 방법을 설명합니다. C 헤더로부터의 브리지 생성이 자동화되었으며, 프로시저럴 스텁이 자동 완성을 제공합니다. glfwGetProcAddress와의 완전한 크로스플랫폼 호환성.

PHP FFI + GLFW: 동적 OpenGL 확장
Advertisement 728x90

PHP FFI에서 GLFW를 통한 동적 OpenGL 로딩

PHP FFI 방식으로 OpenGL을 사용할 때, GLFW3 헤더 파일에서 상수와 typedef를 수동으로 복사하면 불필요한 보일러플레이트 코드가 많이 발생합니다. 우리는 #define 문을 PHP 상수로 변환하고, API 함수는 리소스 섹션에 그대로 삽입합니다.

변환 예시:

// glfw3.h
#define GLFW_VERSION_MAJOR 3

// glfw3.php
const GLFW_VERSION_MAJOR = 3;
// glfw3.h
GLFWAPI void glfwMakeContextCurrent(GLFWwindow* window);

// glfw3.php (in __halt_compiler())
void glfwMakeContextCurrent(GLFWwindow* window);

FFI 함수는 프록시 객체 메서드이자 포인터 역할을 동시에 수행합니다:

Google AdInline article slot
$glfwMakeContextCurrent = $glfw->glfwMakeContextCurrent;
$glfwMakeContextCurrent($window);

자동완성을 위한 절차적 스텁

타이핑과 IDE 지원을 위해 static 포인터 캐싱을 사용한 PHP 래퍼 함수를 생성합니다:

const GLFW_INSTANCE = FFI::cdef(...);

function glfwMakeContextCurrent(mixed ...$args): void {
    static $function = GLFW_INSTANCE->glfwMakeContextCurrent;
    $function(...$args);
}

이 접근 방식은 FFI 프록시 메서드 호출을 클로저로 대체하여 최소화합니다. 함수 주소가 정적이므로 성능이 유지됩니다.

대안(권장하지 않음):

Google AdInline article slot
  • 첫 번째 인수로 $glfw 전달
  • global $glfw 사용

GLFW_INSTANCE 상수를 사용하면 메인 코드가 단순해집니다:

require 'src/glfw3.php';

if (!glfwInit()) exit(-1);
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
$window = glfwCreateWindow(640, 480, 'Hello World', null, null);

opengl32.dll 없이 동적 OpenGL 로딩

OpenGL 함수는 플랫폼 의존적인 GetProcAddress 함수를 통해 동적으로 로드됩니다:

  • Windows: wglGetProcAddress
  • Linux: glXGetProcAddressARB
  • Android: eglGetProcAddress

GLFW는 이를 크로스 플랫폼 glfwGetProcAddress로 통합합니다:

Google AdInline article slot
function glClear(mixed ...$args): void {
    static $function = GLFW_INSTANCE->cast(
        'PFNGLCLEARPROC',
        GLFW_INSTANCE->glfwGetProcAddress('glClear')
    );
    $function(...$args);
}

PFNGLCLEARPROC 같은 타입은 glcorearb.h에서 가져옵니다:

typedef void (*PFNGLCLEARPROC)(GLbitfield mask);

확장 지원(NV, AMD → ARB)은 동적으로 확인됩니다: 하드웨어가 사용 가능한 함수를 결정하고, 드라이버가 누락된 함수를 에뮬레이션합니다.

소스 코드에서 브리지 생성

glfw3.php(2만 줄 이상) 생성 자동화:

  • ffi/preprocessor: C 헤더를 PHP 형식으로 변환, define 추출
  • ffi/ide-helper-generator: 인수 타입이 포함된 스텁 생성

Ubuntu 24.04 호환성을 위해 GLFW 3.3을 선택했습니다. OpenGL 상수와 함수는 단일 파일로 통합되었으며, opengl.php는 제거되었습니다.

장점:

  • ext-glfw와 완전 호환
  • 수동 조정 없이 크로스 플랫폼 지원
  • 컴파일 없이 자동완성 및 타이핑 지원

핵심 포인트

  • GLFW_INSTANCE 글로벌 상수는 전역 변수 없이 빠른 FFI 접근 제공
  • *PFNGLPROC** 타입(glcorearb.h)은 수동 시그니처 지정 없이 캐스팅 단순화
  • glfwGetProcAddress가 플랫폼별(WGL/GLX/EGL) 복잡성 대체
  • 소스에서 생성으로 2만 줄 이상의 코드 최신 상태 보장
  • 성능: 정적 캐시로 FFI 메서드 오버헤드 최소화

다음 파트에서 버퍼와 셰이더로 삼각형을 그릴 준비가 완료되었습니다.

— Editorial Team

Advertisement 728x90

다음 읽기