사용자 정의 함수는 C (또는 언어로 작성할 수 있습니다. C ++와 같은 C와 호환 될 수 있습니다). 그러한 기능은입니다 동적으로로드 가능한 객체 (공유라고도합니다 라이브러리) 및 주문형 서버에 의해로드됩니다. 역학 로딩 기능은 구별되는 것입니다"c 언어"기능"내부"함수 --- 실제 코딩 컨벤션은 본질적으로 두 가지 모두 동일합니다. (따라서 표준 내부 기능 라이브러리는 풍부한 코딩 소스입니다. 사용자 정의 C 함수에 대한 예제.)
현재 두 가지 다른 전화 규칙이 c 기능. 최신"버전 1"전화 컨벤션은 A를 작성하여 표시됩니다.pg_function_info_v1 ()매크로 기능을 요청합니다. 아래 그림과 같이. 그러한 매크로의 부족은 구식을 나타냅니다 ("버전 0") 함수. 언어 지정된 이름함수 만들기isC두 경우 모두. 구식 기능 이식성 문제와 부족으로 인해 이제는 더 이상 사용되지 않습니다. 기능이지만 여전히 호환성을 위해 지원됩니다 이유.
처음으로 사용자 정의 기능이 처음입니다 로드 가능한 객체 파일은 세션에서 호출됩니다. 동적 로더 함수가 될 수 있도록 해당 객체 파일을 메모리에로드합니다. 라고 불리는. 그만큼함수 만들기a 따라서 사용자 정의 C 함수는 두 가지 조각을 지정해야합니다 기능에 대한 정보 :로드 가능한 객체의 이름 파일 및 특정 함수의 C 이름 (링크 기호) 해당 객체 파일 내에서 호출하십시오. C 이름이 명시 적으로없는 경우 그런 다음 지정된 다음 SQL 기능과 동일하다고 가정합니다. 이름.
다음 알고리즘은 공유 객체를 찾는 데 사용됩니다. 에 주어진 이름을 기준으로 파일생성 기능명령 :
이름이 절대 경로 인 경우 주어진 파일은 짐을 실은.
이름이 문자열로 시작하면$ libdir, 그 부분은로 대체됩니다.PostgreSQL패키지 라이브러리 빌드 타임에 결정된 디렉토리 이름
이름에 디렉토리 부분이없는 경우 파일 구성에 의해 지정된 경로에서 검색됩니다. 변하기 쉬운dynamic_library_path.
그렇지 않으면 (파일은 경로에서 발견되지 않았습니다. 비 변제 디렉토리 부분), 동적 로더가 포함되어 있습니다 주어진대로 이름을 가져 가려고 할 것입니다. 실패하다. (현재 작업에 의존하는 것은 신뢰할 수 없습니다 예배 규칙서.)
이 시퀀스가 작동하지 않으면 플랫폼 별 공유 라이브러리 파일 이름 확장 (종종.so)는 주어진 이름과 이것에 추가됩니다 시퀀스가 다시 시도됩니다. 그것이 실패하면 부하가 있습니다 실패하다.
사용자 ID토토 사이트 추천서버는 파일로의 경로를 가로 질러야합니다. 당신은로드하려고합니다. 파일 또는 더 높은 수준의 디렉토리 제작 읽을 수 없거나/또는 실행할 수 없음Postgres사용자는 일반적인 실수입니다.
어쨌든에 나와있는 파일 이름은함수 만들기명령은 문자 그대로 기록됩니다 시스템이 카탈로그가되므로 파일을 다시로드 해야하는 경우 동일한 절차가 적용됩니다.
참고 : PostgreSQLC 함수를 자동으로 컴파일하지 않습니다. 대상 파일은 a에 참조되기 전에 컴파일해야합니다.함수 만들기명령. 보다섹션 33.7.6추가 정보.
처음으로 사용 된 후 동적으로로드 객체 파일은 메모리에 유지됩니다. 같은 미래의 전화 해당 파일의 함수에 대한 세션은 심볼 테이블 조회의 작은 오버 헤드. 강제 a 객체 파일의 새로 고침, 예를 들어 다시 컴파일 한 후 그만큼로드신선한 명령 또는 시작 세션.
공유 라이브러리를 상대적으로 찾는 것이 좋습니다 에게$ libdir또는 동적을 통한 도서관 경로. 이것은 새로운 경우 버전 업그레이드를 단순화합니다 설치는 다른 위치에 있습니다. 실제 디렉토리 저것$ libdirstand는 찾을 수 있습니다 명령과 함께PG_CONFIG --pkglibdir.
전PostgreSQL릴리스 7.2, 객체 파일에 대한 정확한 절대 경로 만 지정함수 만들기. 이것 접근 방식은 이제 기능을 만들기 때문에 더 이상 사용되지 않습니다 불필요하게 정의 할 수 없습니다. 그냥 지정하는 것이 가장 좋습니다 경로 나 확장 상태가없는 공유 라이브러리 이름을 검색 메커니즘 대신 정보를 제공합니다.
토토 사이트 추천language functions를 작성하는 방법을 알기 위해서는 알아야합니다. 어떻게PostgreSQL내부 기본 데이터 유형 및 전달 방법을 나타내고 기능에서. 내부,PostgreSQL기본 토토 사이트 추천을 a로 간주합니다."기억의 블로브". 사용자 정의 토토 사이트 추천을 차례로 정의하는 함수는 길을 정의합니다. 저것PostgreSQL작동 할 수 있습니다 그것. 즉,PostgreSQL의지 디스크에서 데이터를 저장하고 검색하고 사용하십시오. 입력, 프로세스 및 출력에 대한 사용자 정의 함수 데이터.
기본 토토 사이트 추천은 세 가지 내부 형식 중 하나를 가질 수 있습니다.
통과 별 가치, 고정 길이
참조로 통과, 고정 길이
참조별로 전달, 가변 길이
바이 값 토토 사이트 추천은 길이가 1, 2 또는 4 바이트 일 수 있습니다 (또한 8 바이트, ifsizeof (Datum)는 8입니다 기계). 당신은 당신의 토토 사이트 추천을 정의하는 데주의해야합니다. 모든 아키텍처에서 크기 (바이트)가됩니다. 을 위한 예,Long토토 사이트 추천은 위험합니다 일부 기계에서는 4 바이트이고 다른 기계의 8 바이트이기 때문에 반면int타입은 대부분의 유닉스에서 4 바이트입니다 기계. 의 합리적인 구현int4유닉스 머신의 타입 :
/ * 4-byte 정수, 가치에 따라 통과 */ typedef int int4;
반면에, 모든 크기의 고정 길이 토토 사이트 추천이 회의 별 통과. 예를 들어 샘플이 있습니다 A 구현PostgreSQL토토 사이트 추천 :
/ * 16 바이트 구조, 참조로 통과 */ typedef struct 더블 X, y; 가리키다;
전달할 때 그러한 토토 사이트 추천에 대한 포인터 만 사용할 수 있습니다. 그리고PostgreSQL기능. 그러한 유형의 값을 반환하려면 권리를 할당하십시오. 를 가진 메모리의 양Palloc, 채우기 할당 된 메모리를하고 포인터를 반환합니다. (당신도 할 수도 있습니다 반환과 같은 토토 사이트 추천의 입력 값을 반환합니다. 입력 값으로 포인터를 반환하여 직접 값.Never수정 그러나 추천 입력 값의 내용.)
마지막으로 모든 가변 길이 유형도 지나쳐야합니다 참조. 모든 가변 길이 토토 사이트 추천은 길이로 시작해야합니다 정확히 4 바이트의 필드 및 그 안에 저장 될 모든 데이터 토토 사이트 추천은 그 다음에 메모리에 위치해야합니다. 길이 필드. 길이 필드에는 총 길이가 포함됩니다 구조, 즉 길이 필드의 크기가 포함됩니다. 그 자체.
예를 들어, 우리는 토토 사이트 추천을 정의 할 수 있습니다텍스트다음과 같이 :
typedef struct int4 길이; 숯 데이터 [1]; 텍스트;
분명히 여기에 선언 된 데이터 필드는 충분히 길지 않습니다. 가능한 모든 줄을 잡고 있습니다. 선언하는 것은 불가능하기 때문에 의 가변 크기 구조C, 우리는에 대한 지식에 의존합니다.C컴파일러는 범위 점검되지 않습니다 배열 구역. 우리는 필요한 금액을 할당합니다 공간에 배열이 선언 된 것처럼 배열에 액세스하십시오. 올바른 길이. (이것은 당신이 읽을 수있는 일반적인 트릭입니다. C.)에 관한 많은 교과서에서
가변 길이 토토 사이트 추천을 조작 할 때 조심해야합니다 올바른 양의 메모리를 할당하고 길이를 설정하려면 필드가 올바르게. 예를 들어, 우리가 40 바이트를 저장하고 싶다면 에이텍스트구조, 우리는 a를 사용할 수 있습니다 다음과 같은 코드 조각 :
#include "postgres.h" ... 숯 버퍼 [40]; / * 소스 데이터 */ ... 텍스트 *대상 = (텍스트 *) palloc (varhdrsz + 40); 대상- 길이 = varhdrsz + 40; memcpy (대상- 데이터, 버퍼, 40); ...
varhdrsz|sizeof (int4)이지만 좋은 스타일로 간주됩니다 매크로 사용varhdrsz가변 길이 토토 사이트 추천에 대한 오버 헤드 크기.
표 33-1어떤 c 유형이 어떤 SQL 유형에 해당하는지 지정합니다. 내장 유형의 유형을 사용하는 c-language 함수 작성PostgreSQL. 그만큼"" 정의열은 헤더 파일을 제공합니다 토토 사이트 추천 정의를 얻으려면 포함해야합니다. (실제 정의는 나열된 파일. 사용자가 정의 된 것을 고수하는 것이 좋습니다 인터페이스.) 항상 포함해야합니다postgres.h먼저 모든 소스 파일에서 어쨌든 필요한 많은 것들을 선언합니다.
표 33-1. 내장 SQL의 동등한 C 토토 사이트 추천 유형
SQL 유형 | C 토토 사이트 추천 | 정의 |
---|---|---|
Abstime | AbsoluteTime | utils/nabstime.h |
부울 | bool | postgres.h(아마도 컴파일러 내장) |
Box | Box* | utils/geo_decls.h |
BYTEA | BYTEA* | postgres.h |
"char" | char | (컴파일러 내장) |
캐릭터 | BPCHAR* | postgres.h |
CID | CommandId | postgres.h |
날짜 | dateadt | utils/date.h |
smallint(int2) | int2또는int16 | postgres.h |
int2vector | int2vector* | postgres.h |
Integer(int4) | int4또는int32 | postgres.h |
Real(float4) | float4* | postgres.h |
이중 정밀(float8) | float8* | postgres.h |
간격 | 간격* | utils/timestamp.h |
LSEG | lseg* | utils/geo_decls.h |
이름 | 이름 | postgres.h |
OID | OID | postgres.h |
oidvector | oidvector* | postgres.h |
PATH | Path* | utils/geo_decls.h |
포인트 | 포인트* | utils/geo_decls.h |
Regproc | Regproc | postgres.h |
Reltime | Relativetime | utils/nabstime.h |
텍스트 | 텍스트* | postgres.h |
tid | ItemPointer | Storage/itemptr.h |
Time | Timeadt | utils/date.h |
시간대가있는 시간 | Timetzadt | utils/date.h |
타임 스탬프 | 타임 스탬프* | utils/timestamp.h |
TinterVal | TimeInterval | utils/nabstime.h |
Varchar | Varchar* | postgres.h |
xid | TransactionId | postgres.h |
이제 우리는 가능한 모든 구조를 살펴 보았습니다. 기본 유형, 실제 기능의 몇 가지 예를 보여줄 수 있습니다.
우리는를 발표합니다."구식"컨벤션을 먼저 호출합니다 더 이상 사용되지 않으면 처음에 처리하는 것이 더 쉽습니다. 에서 버전 -0 메소드, C 함수의 인수 및 결과 정상적인 C 스타일로 방금 선언되지만 사용에주의를 기울입니다. 위와 같이 각 SQL 데이터 유형의 C 표현.
여기 몇 가지 예가 있습니다.
#include "postgres.h" #include <string.h / * 가치 별 */ int add_one (int arg) 반환 Arg + 1; / * 참조로 고정 길이 */ float8 * add_one_float8 (float8 *arg) float8 *result = (float8 *) palloc (sizeof (float8)); *결과 = *arg + 1.0; 반환 결과; 가리키다 * MakePoint (point *pointx, point *pointy) 지점 *new_point = (point *) palloc (sizeof (point)); new_point- x = pointx- x; new_point- y = pointy- y; New_Point를 반환합니다. / * 참조적으로 가변 길이 */ 텍스트 * 카피 텍스트 (텍스트 *t) /* * varsize는 바이트의 구조물의 총 크기입니다. */ 텍스트 *new_t = (텍스트 *) palloc (varsize (t)); varatt_sizep (new_t) = varsize (t); /* * Vardata는 구조물의 데이터 영역에 대한 포인터입니다. */ memcpy ((void *) vardata (new_t), / *대상 * / (void *) vardata (t), / *소스 * / varsize (t) -varhdrsz); / * 얼마나 많은 바이트 */ 뉴 _t를 반환합니다. 텍스트 * concat_text (text *arg1, text *arg2) int32 new_text_size = varsize (arg1) + varsize (arg2) - varhdrsz; 텍스트 *new_text = (텍스트 *) palloc (new_text_size); varatt_sizep (new_text) = new_text_size; memcpy (vardata (new_text), vardata (arg1), varsize (arg1) -varhdrsz); memcpy (vardata (new_text) + (varsize (arg1) -varhdrsz), vardata (arg2), varsize (arg2) -varhdrsz); new_text를 반환합니다.
위의 코드가 파일에서 준비되었다고 가정funcs.c공유로 컴파일했습니다 객체, 우리는 함수를 정의 할 수 있습니다PostgreSQL다음과 같은 명령과 함께 :
함수 생성 add_one (정수) 정수를 반환합니다 처럼 '디렉토리/funcs ','add_one ' 언어 C 엄격한; - SQL 기능 이름 "add_one"의 과부하 참고 기능 Add_one (이중 정밀)을 작성하십시오. 이중 정밀도를 반환합니다 처럼 '디렉토리/funcs ','add_one_float8 ' 언어 C 엄격한; 함수 makepoint (점, 점)를 반환합니다 처럼 '디렉토리/funcs ','makepoint ' 언어 C 엄격한; 함수 CopyText (텍스트)를 작성합니다 텍스트를 반환합니다 처럼 '디렉토리/funcs ','CopyText ' 언어 C 엄격한; CONCIT CONCAT_TEXT (텍스트, 텍스트) 텍스트를 반환합니다 처럼 '디렉토리/funcs ','concat_text ', 언어 C 엄격한;
여기,디렉토리공유 라이브러리 파일의 디렉토리 (예 :PostgreSQL튜토리얼 디렉토리, 여기에는이 섹션에 사용 된 예제에 대한 코드가 포함되어 있습니다). (더 나은 스타일은 그냥 사용하는 것입니다'funcs'inas조항, 추가 후디렉토리검색 경로로. 어느 쪽이든 사례, 우리는 공유에 대한 시스템 별 확장을 생략 할 수 있습니다. 도서관, 일반적으로.so또는.SL.)
함수를 다음과 같이 지정했음을 알 수 있습니다."엄격한", 시스템은해야한다는 것을 의미합니다 입력 값이 NULL 인 경우 자동으로 NULL 결과를 가정합니다. 이렇게함으로써, 우리는 기능 코드. 이것 없이는 널 값을 확인해야합니다 명시 적으로, 각각에 대한 널 포인터를 확인함으로써 통과 참조 주장. (패스 별 값 주장의 경우, 우리 확인 방법조차 없습니다!)
이 호출 규칙은 사용하기가 간단하지만 매우 휴대 성; 일부 아키텍처에는 문제가 있습니다 보다 작은 데이터 토토 사이트 추천 전달int이 방법. 또한 간단한 방법은 없습니다 귀무 결과를 반환하거나 어떤 널 주장에 대처하기 위해 기능을 엄격하게 만드는 것 외에. 버전 -1 다음에 제시된 컨벤션은 이러한 반대 의견을 극복합니다.
버전 1 호출 컨벤션은 매크로에 의존합니다 통과 된 주장의 복잡성을 억제하고 결과. 버전 -1 기능의 C 선언은 다음과 같습니다 언제나
Datum funcname (pg_function_args)
또한 매크로 호출
pg_function_info_v1 (funcname);
동일한 소스 파일에 나타나야합니다. (전통적으로, 그것은입니다 함수 자체 직전에 작성되었습니다.)이 매크로 호출은 필요하지 않음내부-언어 기능, 이후PostgreSQL모든 내부 기능이 버전 -1을 사용한다고 가정합니다 협약. 그러나 동적으로로드되는 데 필요합니다 기능.
버전 -1 함수에서는 각 실제 인수가 가져옵니다
a 사용pg_getarg_xxx()
매크로에 해당합니다
인수의 데이터 토토 사이트 추천 및 결과는 a를 사용하여 반환됩니다.pg_return_xxx()
반환 토토 사이트 추천의 매크로.pg_getarg_xxx()
그 주장으로 간주합니다
가져 오는 기능 인수 수, 여기서 계산
0에서 시작합니다.pg_return_xxx()
논쟁으로 취합니다
반품 할 실제 가치.
여기서 우리는 Version-1에 코딩 된 위와 동일한 함수를 보여줍니다. 스타일:
#include "postgres.h" #include <string.h #include "fmgr.h" / * 가치 별 */ pg_function_info_v1 (add_one); 자료 add_one (pg_function_args) int32 arg = pg_getarg_int32 (0); pg_return_int32 (arg + 1); / * b 참조, 고정 길이 */ pg_function_info_v1 (add_one_float8); 자료 add_one_float8 (pg_function_args) /* float8의 매크로는 통과 참조 특성을 숨 깁니다. */ float8 arg = pg_getarg_float8 (0); pg_return_float8 (arg + 1.0); pg_function_info_v1 (makepoint); 자료 makepoint (pg_function_args) /* 여기서, 포인트의 추론 특성은 숨겨져 있지 않습니다. */ point *pointx = pg_getarg_point_p (0); point *pointy = pg_getarg_point_p (1); 지점 *new_point = (point *) palloc (sizeof (point)); new_point- x = pointx- x; new_point- y = pointy- y; pg_return_point_p (new_point); / * 참조적으로 가변 길이 */ pg_function_info_v1 (CopyText); 자료 CopyText (pg_function_args) 텍스트 *t = pg_getarg_text_p (0); /* * varsize는 바이트의 구조물의 총 크기입니다. */ 텍스트 *new_t = (텍스트 *) palloc (varsize (t)); varatt_sizep (new_t) = varsize (t); /* * Vardata는 구조물의 데이터 영역에 대한 포인터입니다. */ memcpy ((void *) vardata (new_t), / *대상 * / (void *) vardata (t), / *소스 * / varsize (t) -varhdrsz); / * 얼마나 많은 바이트 */ pg_return_text_p (new_t); pg_function_info_v1 (concat_text); 자료 concat_text (pg_function_args) 텍스트 *arg1 = pg_getarg_text_p (0); 텍스트 *arg2 = pg_getarg_text_p (1); int32 new_text_size = varsize (arg1) + varsize (arg2) - varhdrsz; 텍스트 *new_text = (텍스트 *) palloc (new_text_size); varatt_sizep (new_text) = new_text_size; memcpy (vardata (new_text), vardata (arg1), varsize (arg1) -varhdrsz); memcpy (vardata (new_text) + (varsize (arg1) -varhdrsz), vardata (arg2), varsize (arg2) -varhdrsz); pg_return_text_p (new_text);
the기능 생성명령은입니다 버전 -0 등가와 동일합니다.
언뜻보기에 버전 1 코딩 규칙이 나타날 수 있습니다
무의미한 모호함이되기 위해. 그러나 그들은 제안합니다
매크로가 불필요하게 숨길 수 있기 때문에 개선 횟수
세부 사항. 예를 들어 코딩에서add_one_float8
, 우리는 더 이상 알 필요가 없습니다
저것float8는 추천 토토 사이트 추천입니다.
또 다른 예는getarg가변 길이 토토 사이트 추천의 매크로는보다 효율적입니다
페치"토스트"(압축 또는
외부) 값.
버전 -1 기능의 큰 개선이 더 좋습니다
널 입력 및 결과 처리. 매크로PG_ARGISNULL (n)
함수를 테스트 할 수 있습니다
각 입력이 무효인지 여부. (물론, 이것을하는 것은 전용입니다
선언되지 않은 기능에 필요"엄격한".)와 마찬가지로pg_getarg_xxx()
매크로, 입력 인수
0에서 시작합니다. 하나는 자제해야합니다
실행pg_getarg_xxx()
하나가 확인할 때까지
논쟁은 무효가 아닙니다. 널 결과를 반환하려면 executepg_return_null ()
; 이것은 작동합니다
엄격한 기능과 기적 기능.
새로운 스타일 인터페이스에 제공된 다른 옵션은 2입니다
의 변형pg_getarg_xxx()
매크로. 이 중 첫 번째,pg_getarg_xxx_copy ()
, 반환을 보장합니다
글을 쓰는 데 안전한 지정된 인수의 사본.
(일반 매크로는 때때로 값에 대한 포인터를 반환합니다.
물리적으로 테이블에 저장되어 있어야합니다.
에게. 사용 사용pg_getarg_xxx_copy ()
매크로는 a
쓰기 가능한 결과.) 두 번째 변형은로 구성됩니다.pg_getarg_xxx_slice ()
매크로
세 가지 주장. 첫 번째는 함수의 수입니다
인수 (위와 같이). 두 번째와 세 번째는 오프셋입니다
반환 할 세그먼트의 길이. 오프셋이 계산됩니다
0 및 음의 길이는 나머지가
가치를 반환합니다. 이 매크로는보다 효율적인 액세스를 제공합니다
저장소가있는 경우 큰 값의 일부로
토토 사이트 추천"외부". (스토리지 토토 사이트 추천
열의 열은를 사용하여 지정할 수 있습니다.ALTER
테이블TableNameAlter ColumnColname스토리지 설정StorageType. StorageType중 하나입니다일반, 외부,
확장또는Main.)
마지막으로, 버전 -1 기능 호출 규칙이이를 만듭니다 설정 결과를 반환 할 수 있습니다 (섹션 33.7.9) 및 트리거 함수 구현 (PostgreSQL : 문서 : 7.4 : 와이즈 토토) 및 절차 적 통화 처리기 (47 장). 버전 1 코드도 더 많습니다 버전 -0보다 휴대용 제한을 깨뜨리지 않기 때문입니다 C 표준의 기능 호출 프로토콜 자세한 내용은 보다src/backend/utils/fmgr/readme소스 분포.
보다 진보 된 주제로 돌아 가기 전에 에 대한 몇 가지 코딩 규칙에 대해 토론하십시오.PostgreSQLc-language functions. 그 동안 언어로 작성된 기능을로드 할 수 있습니다. C보다PostgreSQL,이 다른 이유는 일반적으로 (전혀 가능할 때) 어렵습니다. C ++, Fortran 또는 Pascal과 같은 언어는 종종 C와 동일한 통화 협약 인수와 반환 값이 같은 방식. 이러한 이유로, 우리는 당신의 c- 언어라고 가정 할 것입니다 기능은 실제로 C로 작성됩니다.
C 기능 작성 및 구축을위한 기본 규칙은 다음과 같습니다. 다음은 다음과 같습니다.
usePG_CONFIG -includedir-serverPostgreSQL서버 헤더 파일입니다 시스템에 설치 (또는 사용자가 실행 중). 이 옵션은PostgreSQL7.2. 을 위한PostgreSQL7.1 사용해야합니다 옵션-includedir. (PG_CONFIG0이 아닌 상태로 종료됩니다 알 수없는 옵션이 발생하는 경우.) 이전에 릴리스를 위해 7.1 당신은 추측해야 할 것이지만, 그 이후로 현재 전화 규칙이 소개되었을 가능성은 거의 없습니다 그 릴리스를 지원하고 싶다.
메모리를 할당 할 때를 사용하십시오.PostgreSQL기능Palloc
andpfree
해당 C 라이브러리 대신
기능Malloc
및무료
. 에 의해 할당 된 메모리Palloc
해제됩니다
각 트랜잭션이 끝날 때 자동으로 방지합니다
메모리 누출.
항상 구조물의 바이트를 항상 0memset
. 이것 없이는 그렇지 않습니다
해시 인덱스 또는 해시 조인을 지원하기가 어렵습니다.
데이터의 상당한 비트 만 선택해야합니다.
해시를 계산하는 구조. 모든 것을 초기화하더라도
구조의 필드, 정렬 패딩이있을 수 있습니다
쓰레기를 포함 할 수있는 (구조물의 구멍)
값.
대부분의 내부PostgreSQL토토 사이트 추천은postgres.h관리자 인터페이스 (pg_function_args등)fmgr.h이므로 AT를 포함시켜야합니다 최소한이 두 파일. 휴대 할 수있는 이유로 가장 좋습니다 포함하다postgres.h 첫 번째시스템 또는 사용자 헤더 파일. 포함postgres.h포함elog.handPalloc.h당신을 위해.
객체 파일 내에 정의 된 기호 이름은 안됩니다 서로 충돌하거나에 정의 된 기호와 충돌PostgreSQL서버 실행 파일. 당신은 당신의 함수의 이름을 바꿔야합니다 이 효과에 오류 메시지가 표시되는 경우 변수
코드를 컴파일하고 연결하여 동적으로로드PostgreSQL항상 특별해야합니다 깃발. 참조섹션 33.7.6특정 운영 체제.
사용하기 전에PostgreSQL확장 기능이 작성되었습니다 C, 그들은 특별한 생산 방법으로 편집하고 연결되어야합니다. 서버에서 동적으로로드 할 수있는 파일. 장차 ~ 가 되는 정확한, A공유 도서관생성.
이 섹션에 포함 된 것 이상의 정보는 귀하에게 운영 체제의 문서를 읽어야합니다 특히 C 컴파일러의 수동 페이지,CC및 링크 편집기,ld. 또한PostgreSQL소스 코드에는 여러 가지가 포함되어 있습니다 의 작업 예제Contrib디렉토리. 이 예에 의존하면 의 가용성에 따라 모듈PostgreSQL소스 코드.
공유 생성 라이브러리는 일반적으로 실행 파일 연결과 유사합니다 소스 파일은 객체 파일로 컴파일 된 다음 객체 파일은 함께 연결됩니다. 객체 파일은 있어야합니다 생성위치 독립 코드(PIC),개념적으로 그들이 할 수 있음을 의미합니다 로드 될 때 메모리의 임의의 위치에 배치 실행 파일에 의해. (실행 파일을위한 객체 파일은 다음과 같습니다 일반적으로 그런 식으로 컴파일되지 않습니다.) 공유를 연결하라는 명령 라이브러리에는 링크와 구별되는 특수 플래그가 포함되어 있습니다 실행 파일. --- 적어도 이것은 이론입니다. 일부 시스템에서 연습은 훨씬 더 추악합니다.
다음 예에서는 소스 코드가 파일에서foo.c그리고 우리는 a 공유 도서관foo.so. 그만큼 중간 객체 파일은입니다.foo.o47661_47777
생성 할 컴파일러 플래그PICis-fpic. 공유 라이브러리 생성 링커 플래그는입니다.-shared.
gcc -fpic -c foo.c ld -shared -o foo.so foo.o
버전 4.0의 기준으로 적용 가능합니다.BSD/OS.
생성 할 컴파일러 플래그PICis-fpic. 공유 라이브러리를 만들려면 컴파일러 플래그는입니다.-shared.
gcc -fpic -c foo.c gcc -shared -o foo.so foo.o
버전 3.0의 기준으로 적용 가능합니다.freebsd.
생성 할 시스템 컴파일러의 컴파일러 플래그PICis+Z. 사용시GCCit '-fpic. 공유 라이브러리의 링커 플래그 이다-B. 그래서
CC +Z -C foo.c
또는
gcc -fpic -c foo.c
and
ld -B -O Foo.sl foo.o
hp-ux확대.SL공유 대부분의 다른 시스템과 달리 라이브러리.
PIC기본값입니다. 특수 컴파일러 옵션이 필요하지 않습니다. 링커 공유 라이브러리를 생산하는 옵션-shared.
CC -C foo.c ld -shared -o foo.so foo.o
생성 할 컴파일러 플래그PICis-fpic. 어떤 상황에서는 일부 플랫폼에서-fpic-fpic작동하지 않습니다. GCC를 참조하십시오 자세한 내용은 설명서. 컴파일러 플래그를 작성합니다 공유 도서관은-shared. 에이 완전한 예는 다음과 같이 보입니다.
cc -fpic -c foo.c cc -shared -o foo.so foo.o
여기 예입니다. 개발자 도구가 있다고 가정합니다 설치.
CC -C foo.c CC -BUNDLE -FLAT_NAMESPACE- 정의 된 억제 -o foo.so foo.o
생성 할 컴파일러 플래그PICis-fpic. 을 위한ELF시스템, 플래그를 가진 컴파일러-sharedIS 공유 라이브러리를 연결하는 데 사용됩니다. 더 오래된 비 엘프 시스템,ld -BsharableIS 사용된.
gcc -fpic -c foo.c gcc -shared -o foo.so foo.o
생성 할 컴파일러 플래그PICis-fpic. ld -Bsharable링크에 사용됩니다 공유 도서관.
gcc -fpic -c foo.c ld -bsharable -o foo.so foo.o
생성 할 컴파일러 플래그PICis-kpic썬 컴파일러와-fpicwithGCC. 공유 링크 라이브러리, 컴파일러 옵션은입니다.-g컴파일러 또는 대안으로-sharedwithGCC.
cc -kpic -c foo.c cc -g -o foo.so foo.o
또는
gcc -fpic -c foo.c gcc -g -o foo.so foo.o
PIC기본값입니다. 따라서 컴파일 명령은 일반적인 명령입니다.ld특수 옵션과 함께 사용됩니다 링크 :
CC -C foo.c ld -shared -expect_unresolved '*'-o foo.so foo.o
동일한 절차가 GCC 대신 GCC와 함께 사용됩니다. 시스템 컴파일러; 특별한 옵션이 필요하지 않습니다.
생성 할 컴파일러 플래그PICis-K picSCO 컴파일러와-fpicwithgcc. 공유 링크 라이브러리, 컴파일러 옵션은입니다.-gSCO 컴파일러와-sharedwithGCC.
CC -K PIC -C FOO.C cc -g -o foo.so foo.o
또는
gcc -fpic -c foo.c gcc -shared -o foo.so foo.o
팁 :이것이 당신에게 너무 복잡하다면, 당신 사용을 고려해야합니다gnu libtool, 유니폼 뒤에 플랫폼 차이를 숨 깁니다 인터페이스.
결과 공유 라이브러리 파일을로드 할 수 있습니다PostgreSQL. 지정할 때 파일 이름함수 생성명령, 공유 라이브러리 파일의 이름을 알려야합니다. 중간 객체 파일이 아닙니다. 시스템의 경우에 유의하십시오 표준 공유 라이브러리 확장 (일반적으로.so또는.SL) 할 수 있습니다 에서 생략함수 생성명령, 일반적으로 최선을 위해 생략해야합니다 이식성.
다시 참조섹션 33.7.1서버가 공유를 찾을 예정인 위치 도서관 파일.
복합 토토 사이트 추천은 C와 같은 고정 레이아웃이 없습니다. 구조. 복합 유형의 인스턴스는 null을 포함 할 수 있습니다 전지. 또한 AN의 일부인 복합 유형 상속 계층 구조는 다른 필드와 다른 필드를 가질 수 있습니다 동일한 상속 계층의 구성원. 그러므로,PostgreSQL함수를 제공합니다 C에서 복합 토토 사이트 추천의 필드에 액세스하기위한 인터페이스
쿼리에 응답하기 위해 함수를 작성하려고한다고 가정 해 봅시다
이름, c_overpaid (EMP, 1500)를 초과 지불로 선택하십시오 emp에서 여기서 name = 'bill'또는 name = 'sam';
Call Concentions 버전 0 사용c_overpaid
as :
#include "postgres.h" #include "executor/executor.h"/ * for getAttributeByName () */ 부 c_overpaid (tupletableslot *t, / *현재 행의 행 * / int32 한도) bool isnull; INT32 급여; Salary = DatumgetInt32 (getAttributeByName (t, "Salary", & isnull)); if (isnull) 거짓을 반환합니다. 반품 급여 한도;
버전 -1 코딩에서 위는 다음과 같습니다.
#include "postgres.h" #include "executor/executor.h"/ * for getAttributeByName () */ pg_function_info_v1 (c_overpaid); 자료 c_overpaid (pg_function_args) tupleTablesLot *t = (tupleTablesLot *) pg_getarg_pointer (0); int32 한계 = pg_getarg_int32 (1); bool isnull; INT32 급여; Salary = DatumgetInt32 (getAttributeByName (t, "Salary", & isnull)); if (isnull) pg_return_bool (false); /* 또는 널 급여에 대해 pg_return_null ()을 선호 할 수 있습니다. */ pg_return_bool (급여 한도);
getAttributeByName
PostgreSQL시스템 기능
지정된 행에서 속성을 반환합니다. 세 가지가 있습니다
인수 : 유형의 주장tupletableslot*이름, 이름으로 전달되었습니다
원하는 속성 및 반환 매개 변수의
속성이 null인지 여부.getAttributeByName
a 반환Datum적절한 데이터로 변환 할 수있는 값
적절한 사용으로 입력Datumgetxxx()
매크로.
다음 명령은 함수를 선언합니다c_overpaid
sql :
함수 생성 C_OVERPAID (EMP, Integer)는 부울을 반환합니다 처럼 '디렉토리/funcs ','c_overpaid ' 언어 C;
c- 언어에서 행 또는 복합 유형 값을 반환하려면 기능, 매크로를 제공하는 특수 API를 사용할 수 있으며 구성 복합재의 복잡성의 대부분을 숨기는 기능 데이터 유형. 이 API를 사용하려면 소스 파일에는 다음을 포함해야합니다.
#include "funcapi.h"
복합 데이터 유형 (또는 행)을 반환하기위한 지원 부터 시작합니다.AttinMetadata구조. 이 구조에는 개별 속성의 배열이 있습니다 RAW C 문자열에서 행을 생성하는 데 필요한 정보. 그만큼 구조에 포함 된 정보는 A에서 파생됩니다.tupledesc구조 각 호출에 대한 중복 계산을 피하기 위해 저장되었습니다. 설정 반복 기능 (다음 섹션 참조). a 기능을 반환하는 함수,AttinMetadata구조를 계산해야합니다 첫 번째 통화 중에 한 번, 이후 통화로 재사용을 위해 저장되었습니다.AttinMetadata또한 포인터를 저장합니다 원래tupledesc.
typedef struct attinmetadata / * 전체 tupledesc */ tupledesc tupdesc; / * 속성 유형 입력 함수 finfo */ fmgrinfo *Attinfuncs; / * 속성 유형 typelem 배열 */ oid *attelems; / * 속성 TypMod 배열 */ int32 *atttypmods; attinmetadata;
이 구조를 채우는 데 도움이됩니다 기능과 매크로를 사용할 수 있습니다. 사용
tupledesc relationnamegetTupledesc (const char *relname)
atupledesc이름이 지정되었습니다 관계, 또는
tupledesc typegetTupledesc (Oid typeoid, list *colaliases)
atupledesc기준 a OID를 입력하십시오. 이것은 A를 얻는 데 사용될 수 있습니다.tupledesc베이스 또는 복합 유형의 경우. 그 다음에
Attinmetadata *tupledescgetattinmetadata (tupledesc tupdesc)
포인터를 반환합니다AttinMetadata, 주어진 것에 따라 초기화tupledesc. Attinmetadata와 함께 사용할 수 있습니다 C 문자열을 올바르게 형성된 행 값을 생성하기위한 문자열 (내부적으로 튜플이라고 함).
튜플을 반환하려면을 기준으로 튜플 슬롯을 만들어야합니다.tupledesc. 사용할 수 있습니다
tupletableslot *tupledescgetSlot (tupledesc tupdesc)
이 튜플 슬롯을 초기화하거나 다른 슬롯을 얻으려면 (사용자 제공) 수단. A를 만들려면 튜플 슬롯이 필요합니다Datum함수에 의한 반환. 그만큼 각 통화에서 동일한 슬롯이 재사용 될 수 있습니다.
건설 후AttinMetadata구조,
Heatpuple buildtuplefflfflfflfflings (AttinMetadata *AttinMeta, char ** value)
a를 구축하는 데 사용할 수 있습니다.HeappupleC 문자열 양식의 사용자 데이터가 주어졌습니다.값는 각각의 C 문자열 배열입니다 리턴 행의 속성. 각 C 문자열은 안에 있어야합니다 속성 데이터 토토 사이트 추천의 입력 함수에 의해 예상되는 양식. 속성 중 하나에 대해 널 값을 반환하기 위해 해당 포인터에서값배열을 설정해야합니다NULL. 이것 각 행마다 기능을 다시 호출해야합니다. 반품.
튜플 빌딩tupledescgetattinmetadata
및BuildTupleFromCstrings
편리한 경우에만 편리합니다
귀하의 기능은 자연스럽게 반환 할 값을 계산합니다.
텍스트 문자열. 코드가 자연스럽게 값을 a로 계산하는 경우
세트Datum값, 대신
기본 기능 사용heap_formtuple
변환하려면Datum튜플로 직접 값을 값. 당신은 여전히 할 것입니다
필요tupledesc및 ATupleTablesLot하지만Attinmetadata.
일단 기능에서 돌아 오기 위해 튜플을 만들면 It A로 변환해야합니다.Datum. 사용
tuplegetDatum (tupletableslot *슬롯, 무거운 튜플)
aDatum튜플과 a 슬롯. 이것Datum직접 반환 할 수 있습니다 단일 행 만 반환하려는 경우 정리 함수의 현재 반환 값.
다음 섹션에 예제가 나타납니다.
지원을 제공하는 특별한 API도 있습니다. C-Language 함수의 반환 세트 (다중 행). 에이 설정 퇴행 기능은 버전 -1 호출을 따라야합니다 규칙. 또한 소스 파일은 포함해야합니다.funcapi.h, 위와 같이.
세트 리턴 기능 (SRF) 각 항목마다 한 번 호출됩니다 보고. 그만큼SRF필수 그러므로 그것이하고있는 일을 기억하기에 충분한 상태를 절약하고 각 통화에서 다음 항목을 반환하십시오. 구조FUNCCALLCONTEXT제어를 돕기 위해 제공됩니다 이 과정. 함수 내에서fcinfo- flinfo- fn_extraa 포인터에 대한FUNCCALLCONTEXT가로 질러 전화.
typedef struct /* * 우리가 전에 전화를 한 횟수 * * call_cntr은 srf_firstcall_init ()에 의해 당신을 위해 0으로 초기화됩니다. * srf_return_next ()가 호출 될 때마다 당신을 위해 증분합니다. */ UINT32 CALL_CNTR; /* * 선택적 최대 통화 수 * * max_calls는 편의를 위해서만 여기에 있으며 선택 사항입니다. * 설정하지 않으면 언제 * 기능이 완료되었습니다. */ UINT32 MAX_CALLS; /* * 결과 슬롯에 대한 선택적 포인터 * * 슬롯은 튜플을 반환 할 때 사용합니다 (즉, 복합 데이터 유형) * 기본 데이터 유형을 반환 할 때 필요하지 않습니다. */ tupletableslot *슬롯; /* * 기타 사용자 제공 컨텍스트 정보에 대한 선택적 포인터 * * user_fctx는 자신의 데이터에 대한 포인터로 사용하기위한 것입니다. * 기능의 호출 사이의 임의의 컨텍스트 정보. */ void *user_fctx; /* * 구조물 포함 속성 유형 입력 메타 데이터에 대한 선택적 포인터 * * Attinmeta는 튜플을 반환 할 때 사용합니다 (즉, 복합 데이터 유형) * 기본 데이터 유형을 반환 할 때 필요하지 않습니다. 그것 * BuildTupleFromCstrings ()를 사용하여 생성하려는 경우에만 필요합니다. * 리턴 튜플. */ Attinmetadata *Attinmeta; /* * 여러 통화를 위해 살아야하는 구조에 사용되는 메모리 컨텍스트 * * multi_call_memory_ctx는 SRF_FIRSTCALL_INIT ()에 의해 설정되어 사용됩니다. * 청소용 srf_return_done ()에 의해. 가장 적절한 메모리입니다 * 여러 통화에서 재사용 할 메모리에 대한 컨텍스트 * SRF. */ MemoryContext multi_call_memory_ctx; funcCallContext;
anSRF몇 가지를 사용합니다 자동으로 조작하는 함수와 매크로FUNCCALLCONTEXT구조 (및 를 통해 찾을 것으로 예상fn_extra). 사용
SRF_IS_FIRSTCALL ()
첫 번째 기능이 호출되는지 확인하려면 또는 후속 시간. 첫 번째 통화 (전용)에서
SRF_FIRSTCALL_INIT ()
초기화하려면FUNCCALLCONTEXT. 모든 기능 호출에서 첫 번째, 사용
srf_percall_setup ()
사용을 위해 올바르게 설정하려면FUNCCALLCONTEXT이전에 지우십시오 이전 패스에서 남은 반환 데이터.
함수가 반환 할 데이터가 있으면
srf_return_next (funcctx, result)
발신자에게 반환합니다. (결과토토 사이트 추천이어야합니다Datum, 단일 위에서 설명한대로 준비한 값 또는 튜플.) 마지막으로, 언제 귀하의 기능은 데이터 반환 데이터를 완료했습니다. 사용
srf_return_done (funcctx)
정리하고 끝내려면SRF.
SRF는 일시적인 컨텍스트입니다
통화간에 지워집니다. 이것은 당신이 필요하지 않다는 것을 의미합니다
전화하려면pfree
사용 할당Palloc
; 그것은 할 것입니다
어쨌든 가십시오. 그러나 데이터를 할당하려면
전화를 가로 질러 살 수있는 구조, 당신은 그들을 어딘가에 두어야합니다.
또 다른. 에 의해 언급 된 메모리 컨텍스트multi_call_memory_ctx는 적합한 위치입니다
까지 생존 해야하는 모든 데이터의 경우SRF가 끝났습니다. 대부분의 경우
이것은 당신이로 전환해야한다는 것을 의미합니다.multi_call_memory_ctx일차 설정.
완전한 의사 코드 예제는 다음과 같습니다.
Datum my_set_returning_function (pg_function_args) funccallcontext *funcctx; 데이텀 결과; MemoryContext OldContext;필요에 따른 추가 선언if (srf_is_firstcall ()) funcctx = srf_firstcall_init (); OldContext = MemoryContexTswitchto (funcctx- multi_call_memory_ctx); / * 일회성 설정 코드가 여기에 나타납니다 : */사용자 코드 복합재를 반환하는 경우 tupledesc 빌드 및 아마도 AttinMetadata 슬롯 획득funcctx- 슬롯 = 슬롯;Endif Returning Composite 사용자 코드MemoryContexTswitchto (OldContext); / * 매번 설정 코드가 나타납니다. */사용자 코드funcctx = srf_percall_setup ();사용자 코드/ * 이것은 우리가 끝났는지 테스트 할 수있는 한 가지 방법 일뿐입니다. */ if (funcctx- call_cntr <funcctx- max_calls) / * 여기서 우리는 다른 항목을 반환하고 싶습니다 : */사용자 코드 결과 기준 획득srf_return_next (funcctx, result); 또 다른 / * 여기서 우리는 반환 품목을 완료하고 청소하면됩니다 : */사용자 코드srf_return_done (funcctx);
간단한 완전한 예SRF복합 토토 사이트 추천 모양을 반환합니다 좋다:
pg_function_info_v1 (testpassbyval); 자료 TestPassByVal (pg_function_args) funccallcontext *funcctx; int call_cntr; int max_calls; tupledesc tupdesc; tupletableslot *슬롯; Attinmetadata *Attinmeta; / * 기능의 첫 번째 호출에서만 수행 된 작업 */ if (srf_is_firstcall ()) MemoryContext OldContext; / * 크로스 콜 지속성을위한 함수 컨텍스트 생성 */ funcctx = srf_firstcall_init (); / * 여러 기능 호출에 적합한 메모리 컨텍스트로 전환 */ OldContext = MemoryContexTswitchto (funcctx- multi_call_memory_ctx); / * 반환 할 튜플의 총 수 */ funcctx- max_calls = pg_getarg_uint32 (0); / * __testpassByval 튜플에 대한 튜플 설명 구축 */ tupdesc = relationnamegetTupledesc ( "__ testpassbyval"); / *이 tupdesc와 함께 튜플 슬롯을 할당 */ 슬롯 = tupledescgetSlot (tupdesc); / * 함수 컨텍스트에 슬롯 할당 */ funcctx- 슬롯 = 슬롯; /* * RAW에서 튜플을 생산하는 데 필요한 속성 메타 데이터 생성 * C 문자열 */ Attinmeta = tupledescgetattinmetadata (tupdesc); funcctx- attinmeta = Attinmeta; MemoryContexTswitchto (OldContext); / * 함수의 모든 호출에서 수행 된 작업 */ funcctx = srf_percall_setup (); call_cntr = funcctx- call_cntr; max_calls = funcctx- max_calls; 슬롯 = funcctx- 슬롯; Attinmeta = funcctx- attinmeta; if (call_cntr <max_calls) / * 보내기에 남은 것이 더있을 때 * / char ** 값; 핵심 튜플; 데이텀 결과; /* * 슬롯에 저장을위한 값 배열을 준비하십시오. * 이것은 C 줄 배열이어야합니다. * 나중에 유형 입력 함수에 의해 처리됩니다. */ 값 = (char **) palloc (3 *sizeof (char *)); 값 [0] = (char *) palloc (16 * sizeof (char)); 값 [1] = (char *) palloc (16 * sizeof (char)); 값 [2] = (char *) palloc (16 * sizeof (char)); snprintf (값 [0], 16, "%d", 1 * pg_getarg_int32 (1)); snprintf (값 [1], 16, "%d", 2 * pg_getarg_int32 (1)); snprintf (값 [2], 16, "%d", 3 * pg_getarg_int32 (1)); / * 튜플 구축 */ 튜플 = buildTupleFromCstrings (AttinMeta, 값); / * 튜플을 데이텀으로 만듭니다 */ 결과 = tuplegetDatum (슬롯, 튜플); / * 정리 (정말로 필요하지 않습니다) */ pfree (값 [0]); pfree (값 [1]); pfree (값 [2]); pfree (값); srf_return_next (funcctx, 결과); else / * 더 이상 남지 않을 때하십시오 * / srf_return_done (funcctx);
이 기능을 선언하는 SQL 코드는 다음과 같습니다.
유형 생성 __testpassByval AS (F1 Integer, F2 Integer, F3 Integer); 기능 testpassbyval (정수, 정수)을 만들거나 교체하십시오 처럼 'filename','TestPassbyval ' 언어 c 불변의 엄격한;
디렉토리Contrib/TableFuncin 소스 분포에는 더 많은 세트 리턴 링의 예가 포함되어 있습니다 기능.
c-language 함수는 수락 및 반환으로 선언 될 수 있습니다 다형성 유형AnylementandAnyArray. 보다섹션 33.2.5다형성에 대한 자세한 설명 기능. 기능 인수 또는 반환 유형이 정의 된 경우 다형성 유형으로서 기능 저자는 알 수 없습니다 호출 할 데이터 유형을 전진 시키거나 반품. 에 제공된 두 가지 루틴이 있습니다.fmgr.h버전 -1 C 함수를 허용합니다 인수의 실제 데이터 토토 사이트 추천과 토토 사이트 추천을 발견하십시오. 돌아올 것으로 예상됩니다. 루틴은라고합니다.get_fn_expr_rettype (fmgrinfo *flinfo)andget_fn_expr_argtype (fmgrinfo *flinfo, int Argnum). 결과 또는 인수 유형 OID를 반환합니다.Invalidoid정보가없는 경우 사용 가능. 구조flinfois 일반적으로 액세스 됨74999_75018. 매개 변수argnum는 0 기반입니다.
예를 들어, 수락 할 함수를 작성하고 싶다고 가정합니다. 모든 토토 사이트 추천의 단일 요소 및 1 차원 배열을 반환합니다. 그 토토 사이트 추천의 :
pg_function_info_v1 (make_array); 자료 make_array (pg_function_args) ArrayType *결과; OID Element_Type = get_fn_expr_argtype (fcinfo- flinfo, 0); 데이텀 요소; int16 typlen; 부리 타자 발; 숯 타입자; int ndims; int dims [maxdim]; int lbs [maxdim]; if (! oidisvalid (element_type)) elog (오류, "입력의 데이터 유형을 결정할 수 없음"); / * 제공된 요소 가져 오기 */ 요소 = pg_getarg_datum (0); / * 우리는 하나의 차원이 있습니다 */ ndims = 1; / * 및 하나의 요소 */ 희미한 [0] = 1; / * 그리고 하한은 1 */ lbs [0] = 1; / * 요소 유형에 대한 필수 정보 받기 */ get_typlenbyvalalign (element_type, & typlen, & typbyval, & typalign); / * 이제 배열을 빌드 */ result = construct_md_array (& element, ndims, dims, lbs, element_type, typlen, typbyval, typalign); pg_return_arraytype_p (결과);
다음 명령은 함수를 선언합니다make_array
sql :
함수 생성 make_array (Anylement)는 anyArray를 반환합니다 처럼 '디렉토리/funcs ','make_array ' 언어 C 엄격한;
사용에 유의하십시오엄격한; 이것은 코드가 널에 대한 테스트를 귀찮게하지 않기 때문에 필수 입력.