Reputation: 4385
I am trying to compile a C function for use in Postgres 9.5. When I try running the makefile to compile the code, I get these messages/errors:
cc -o int_to_id.o -c int_to_id.c -I /usr/include/postgresql/9.5/server
In file included from int_to_id.c:1:0:
int_to_id.c: In function ‘int_to_id’:
/usr/include/postgresql/9.5/server/postgres.h:613:26: warning: initialization makes pointer from integer without a cast [-Wint-conversion]
#define DatumGetInt64(X) ((int64) GET_8_BYTES(X))
^
/usr/include/postgresql/9.5/server/fmgr.h:238:29: note: in expansion of macro ‘DatumGetInt64’
#define PG_GETARG_INT64(n) DatumGetInt64(PG_GETARG_DATUM(n))
^
int_to_id.c:55:15: note: in expansion of macro ‘PG_GETARG_INT64’
long *x = PG_GETARG_INT64(0);
^
In file included from int_to_id.c:2:0:
/usr/include/postgresql/9.5/server/fmgr.h:305:30: error: expected expression before ‘return’
#define PG_RETURN_POINTER(x) return PointerGetDatum(x)
^
/usr/include/postgresql/9.5/server/fmgr.h:316:32: note: in expansion of macro ‘PG_RETURN_POINTER’
#define PG_RETURN_VARCHAR_P(x) PG_RETURN_POINTER(x)
^
int_to_id.c:60:12: note: in expansion of macro ‘PG_RETURN_VARCHAR_P’
return PG_RETURN_VARCHAR_P(cstring_to_text(result));
^
Makefile:15: recipe for target 'int_to_id.o' failed
make: *** [int_to_id.o] Error 1
It looks like one of these errors is from the syntax of "fmgr.h", and I'm not sure how to make sense of it, since this is an included library file. How do I go about fixing this error?
For reference, my makefile:
MODULES = int_to_id
PG_CONFIG = pg_config
PGXS = $(shell $(PG_CONFIG) --pgxs)
INCLUDEDIR = $(shell $(PG_CONFIG) --includedir-server)
include $(PGXS)
int_to_id.so: int_to_id.o
cc -shared -o int_to_id.so int_to_id.o
int_to_id.o: int_to_id.c
cc -o int_to_id.o -c int_to_id.c $(CRFLAGS) -I $(INCLUDEDIR)
Also for reference, the C source file:
#include "postgres.h"
#include "fmgr.h"
#ifdef PG_MODULE_MAGIC
PG_MODULE_MAGIC;
#endif
const char charmap[36] = {
'0',
'1',
'2',
'3',
'4',
'5',
'6',
'7',
'8',
'9',
'a',
'b',
'c',
'd',
'e',
'f',
'g',
'h',
'i',
'j',
'k',
'l',
'm',
'n',
'o',
'p',
'q',
'r',
's',
't',
'u',
'v',
'w',
'x',
'y',
'z'
};
Datum int_to_id(PG_FUNCTION_ARGS);
PG_FUNCTION_INFO_V1(int_to_id);
Datum int_to_id(PG_FUNCTION_ARGS){
char result[10] = {' ',' ',' ',' ',' ',' ',' ',' ',' ',' '};
long base_val = 1L;
long *x = PG_GETARG_INT64(0);
for (int i = 1; i <= 10, i++; ){
result[10 - i] = charmap[ ((*x) / base_val) % 36];
}
base_val = base_val * 36L;
return PG_RETURN_VARCHAR_P(cstring_to_text(result));
}
Upvotes: 4
Views: 140
Reputation: 6134
PG_GETARG_INT64(0)
returns a Datum
value as an int64
. You are assigning the value to a pointer (long *
) and this makes the compiler unhappy.
If you know what you are doing, you may force the assignment by casting:
long *x = (long *)PG_GETARG_INT64(0);
But this looks very suspicious to me, and there is probably a better way to do it using PostgresQL types and macros.
For example, this would look better:
int64 x = PG_GETARG_INT64(0);
for (int i = 1; i++; i <= 10){
result[10 - i] = charmap[(x / 36^i) % 36];
}
return PG_RETURN_VARCHAR_P(cstring_to_text(result));
ends up being expanded to
return return PointerGetDatum(cstring_to_text(result))
This is obviously wrong. Remove the extraneous return
:
PG_RETURN_VARCHAR_P(cstring_to_text(result));
Upvotes: 4