C++ postgresql c-extension加载另一个外部库

C++ postgresql c-extension加载另一个外部库,c++,c,postgresql,linker,phash,C++,C,Postgresql,Linker,Phash,我需要比较pHashes(phash.org)和hamming距离函数 我试过pg_相似性中的一个,但似乎不起作用。(相同相位的汉明距离不为0) 所以我想我应该使用一个c扩展来使用pHash库中的ph\u hamming\u distance函数 我得到的是: 相位H.c SQL 我得到的错误: ERROR: could not load library "/usr/lib/postgresql/phash.so": /usr/lib/postgresql/phash.so: undefine

我需要比较pHashes(phash.org)和hamming距离函数

我试过pg_相似性中的一个,但似乎不起作用。(相同相位的汉明距离不为0)

所以我想我应该使用一个c扩展来使用pHash库中的
ph\u hamming\u distance
函数

我得到的是: 相位H.c

SQL

我得到的错误:

ERROR:  could not load library "/usr/lib/postgresql/phash.so": /usr/lib/postgresql/phash.so: undefined symbol: _Z16pg_detoast_datumP7varlena

无论如何,我一定没有正确地链接到postgresql?

我仍然相信可能有更好的方法,但这就是我所做的工作

(我将添加范围检查,而不仅仅是假设所有bytea都是4字节……最终,在生产中留下一个潜在的segfault将是不好的,所以这只是一个玩具项目,这是一件好事)

c-纯c文件,用gcc编译

#include <postgres.h>
#include <fmgr.h>
#include <utils/bytea.h>
#include <utils/datum.h>

//typedef unsigned __int64 ulong64;
#if defined(_MSC_VER) || defined(__BORLANDC__)
typedef unsigned __int64 ulong64;
#else
typedef unsigned long long ulong64;
#endif

extern int32 c_ph_hamming_distance (ulong64 b1, ulong64 b2);

#ifdef PG_MODULE_MAGIC
PG_MODULE_MAGIC;
#endif

PG_FUNCTION_INFO_V1(phash_hamming);
Datum phash_hamming(PG_FUNCTION_ARGS) {

    bytea *bytea1 = PG_GETARG_BYTEA_P(0);
    bytea *bytea2 = PG_GETARG_BYTEA_P(1);
    //FIXME - length of bytea1 & bytea2 must be 4 bytes (64bits)

    ulong64 long1 = *((ulong64*) bytea1);
    ulong64 long2 = *((ulong64*) bytea2);

    int32 ret = c_ph_hamming_distance(long1, long2);

    PG_RETURN_INT32(ret);
}
SQL-相同

CREATE FUNCTION phash_hamming (bytea1 bytea, bytea2 bytea) RETURNS int AS '$libdir/phash' LANGUAGE C;

这是个老问题,但是

  • 不需要添加额外的包装文件并使用gcc编译它
  • PostgreSQL头和PostgreSQL宏都需要外部“C”

    extern "C" {
      #include <postgres.h>
      #include <fmgr.h>
      #ifdef PG_MODULE_MAGIC
      PG_MODULE_MAGIC
      #endif
    }
    
    extern“C”{
    #包括
    #包括
    #ifdef PG_模块
    PG_模块_魔术
    #恩迪夫
    }
    

  • 抱歉,应该先谷歌,这是一个C++/C链接问题,仍然不知道解决方案。似乎是对的,因为当你需要一个PURE C应用程序(PostgreSQL)调用C++库时,你需要一些东西从C++约定到C++约定。不过,您可以将扩展函数的声明放在
    extern“C”
    块中,而不需要两个文件?
    #include <postgres.h>
    #include <fmgr.h>
    #include <utils/bytea.h>
    #include <utils/datum.h>
    
    //typedef unsigned __int64 ulong64;
    #if defined(_MSC_VER) || defined(__BORLANDC__)
    typedef unsigned __int64 ulong64;
    #else
    typedef unsigned long long ulong64;
    #endif
    
    extern int32 c_ph_hamming_distance (ulong64 b1, ulong64 b2);
    
    #ifdef PG_MODULE_MAGIC
    PG_MODULE_MAGIC;
    #endif
    
    PG_FUNCTION_INFO_V1(phash_hamming);
    Datum phash_hamming(PG_FUNCTION_ARGS) {
    
        bytea *bytea1 = PG_GETARG_BYTEA_P(0);
        bytea *bytea2 = PG_GETARG_BYTEA_P(1);
        //FIXME - length of bytea1 & bytea2 must be 4 bytes (64bits)
    
        ulong64 long1 = *((ulong64*) bytea1);
        ulong64 long2 = *((ulong64*) bytea2);
    
        int32 ret = c_ph_hamming_distance(long1, long2);
    
        PG_RETURN_INT32(ret);
    }
    
    #include <pHash.h>
    extern "C" {
        int c_ph_hamming_distance (ulong64 b1, ulong64 b2){
            return ph_hamming_distance(b1, b2);
        }
    }
    
    CFLAGS=-I/usr/include/postgresql/server
    LDFLAGS=-lpHash
    all: phash.so
    
    phash_wrapper.o: phash_wrapper.cpp
        $(CXX) $(CXXFLAGS) -fpic -c phash_wrapper.cpp
    
    phash.o: phash.c
        $(CC) $(CFLAGS) -fpic -c phash.c
    
    phash.so: phash.o phash_wrapper.o
        $(CC) $(LDFLAGS) -shared -o phash.so phash.o phash_wrapper.o
    
    install:
        cp phash.so `pg_config --pkglibdir`
    
    clean:
        rm -f phash.o phash.so phash_wrapper.o
    
    CREATE FUNCTION phash_hamming (bytea1 bytea, bytea2 bytea) RETURNS int AS '$libdir/phash' LANGUAGE C;
    
    extern "C" {
      #include <postgres.h>
      #include <fmgr.h>
      #ifdef PG_MODULE_MAGIC
      PG_MODULE_MAGIC
      #endif
    }