zend_parse_parameters 함수를 사용합니다.
아마 매크로겠지만 그런 것 까지 신경쓰진 않습니다. ㅎㅎ
함수 만들기 기본 설명, 상세 파라미터 종류 들은 http://www.php.net/manual/en/internals2.funcs.php 에서 볼 수 있습니다..만 퍼옵니다.
Spec |
Type |
Locals |
a |
array |
zval* |
A |
array or object |
zval* |
b |
boolean |
zend_bool |
C |
class |
zend_class_entry* |
d |
double |
double |
f |
function |
zend_fcall_info*, zend_fcall_info_cache* |
h |
array |
HashTable* |
H |
array or object |
HashTable* |
l |
long |
long |
L |
long (limits out-of-range LONG_MAX/LONG_MIN) |
long |
o |
object |
zval* |
O |
object (of specified zend_class_entry) |
zval*, zend_class_entry* |
p |
string (a valid path) |
char*, int |
r |
resource |
char* |
s |
string |
char*, int |
z |
mixed |
zval* |
Z |
mixed |
zval** |
3번째 파라메터 문자열은 어떤 변수타입들을 받을지, 4번째 이후는 받을 변수들입니다.
zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "받을변수타입들", &변수1, &변수2, ....)
간단히 예시로 정리하면..
// bool : zend_bool PHP_FUNCTION(test_func1) { zend_bool bool_test; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "b", &bool_test) == FAILURE) { RETURN_NULL(); } if(bool_test==1) { // true } else { // false } RETURN_NULL(); }
// long PHP_FUNCTION(test_func2) { long long_test; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &long_test) == FAILURE) { RETURN_NULL(); } RETURN_NULL(); }
// string PHP_FUNCTION(test_func3) { char* str_test; int str_test_len; // 문자열의 경우 파라메터가 무조건 2개임을 명심.. if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &str_test, &str_test_len) == FAILURE) { RETURN_NULL(); } RETURN_NULL(); }
여러개일 경우는 그냥 타입을 여러개 쓰고 문자열같은 경우는 깊이값도 같이 받아주면 됩니다.
// multiple params PHP_FUNCTION(test_func4) { long a; double b; zend_bool c; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ldb", &a, &b, &c) == FAILURE) { RETURN_NULL(); } RETURN_NULL(); }
// multiple params with string PHP_FUNCTION(test_func5) { long a; double b; zend_bool c; char * d; int d_len; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ldb", &a, &b, &c, &d, &d_len) == FAILURE) { RETURN_NULL(); } RETURN_NULL(); }
리턴도 간단합니다.
자세한건 이 링크를 참고하면 되고.. http://docstore.mik.ua/orelly/webprog/php/ch14_08.htm
다른 타입들도 맞춰서 하면 됩니다. 잘 정리되어있네요.
RETURN_RESOURCE(int r); RETURN_BOOL(int b) ; RETURN_NULL( ); RETURN_LONG(int l) ; RETURN_DOUBLE(double d) ; RETURN_STRING(char *s, int dup) ; RETURN_STRINGL(char *s, int l, int dup); RETURN_EMPTY_STRING( ); RETURN_FALSE ; RETURN_TRUE; RETVAL_RESOURCE(int r); RETVAL_BOOL(int b); RETVAL_NULL( ); RETVAL_LONG(int l); RETVAL_DOUBLE(double d); RETVAL_STRING(char *s, int dup); RETVAL_STRINGL(char *s, int l, int dup); RETVAL_EMPTY_STRING( ); RETVAL_FALSE; RETVAL_TRUE;
// return null PHP_FUNCTION(test_func_ret1) { RETURN_NULL(); }
조금 골치 아픈 건 배열이나 클래스인데 배열만 좀 써보면..
// assoc_array PHP_FUNCTION(test_func_ret2) { // return_value 는 zval* 타입입니다. // 선언은? 글로벌인지 로컬인지 모르겠지만 어딘가에서 해놨나봅니다. 다시 선언하면 오류납니다. array_init(return_value); add_assoc_long(return_value, "x", 123); add_assoc_double(return_value, "y", 456.7); }
이러면 됩니다.
따로 return 명령을 내리지 않아도 리턴이 됩니다.
PHP에서 받아보면 이런 형태죠
<?php $ret = test_func_ret2(); var_dump($ret); ?>
array(2) {
["x"]=>
int(123)
["y"]=>
float(456.7)
}
그럼 배열 안의 배열은 ? (subarray)
어떤 함수가 있는지는 PHP 페이지에 있습니다. http://www.php.net/manual/ro/internals2.variables.arrays.php
// sub_array PHP_FUNCTION(test_func_ret3) { zval *subarray; // 요걸 하나 만들어둡니다. int i; array_init(return_value); // 당연히 초기화 하고 for(i=0; i<3; i++) // 3개를 추가해보겠습니다. { MAKE_STD_ZVAL(subarray); // 이름봐선 데이터를 널이나 0으로 채워주는 놈인가봅니다... array_init(subarray); // 추가할 서브배열도 초기화하고 // 값들을 집어넣습니다. add_assoc_long(subarray, "x", 123); add_assoc_double(subarray, "y", 456.7); // 리턴할 값에 서브배열을 추가합니다. add_next_index_zval(return_value, subarray); } }
결과를 찍어보면?
<?php $ret = test_func_ret3(); var_dump($ret); ?>
요렇게 나오겠죠
array(3) {
[0]=>
array(2) {
["x"]=>
int(123)
["y"]=>
float(456.7)
}
[1]=>
array(2) {
["x"]=>
int(123)
["y"]=>
float(456.7)
}
[2]=>
array(2) {
["x"]=>
int(123)
["y"]=>
float(456.7)
}
}