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)
}