0

pHashes(phash.org)をハミング距離関数と比較する必要があります。

pg_similarityのものを試しましたが、正しく機能していないようです。(同一のpHashのハミング距離は0ではありません)。

ph_hamming_distanceそのため、pHashライブラリの一部である関数を使用するためにc-extensionを使用するだけだと思いました。

私が持っているもの:phash.c

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

#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 = ph_hamming_distance(long1, long2);

    PG_RETURN_INT32(ret);
}

Makefile

CXXFLAGS=-I/usr/include/postgresql/server
LDFLAGS=-Bstatic -lpHash
all: phash.o

phash.o:
    $(CXX) $(CXXFLAGS) -fpic -c phash.c
    $(CXX) $(LDFLAGS) -shared -o phash.so phash.o

install:
    cp phash.so `pg_config --pkglibdir`

clean:
    rm -f phash.o phash.so

SQL

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

私が得ているエラー:

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

どういうわけかpostgresqlに正しくリンクしてはいけませんか?

4

2 に答える 2

2

古い質問ですが...

  1. 余分なラッパー ファイルを追加して gcc を使用してコンパイルする必要はありません。
  2. PostgreSQL ヘッダーと PostgreSQL マクロの両方に extern "C" が必要です。

    extern "C" {
      #include <postgres.h>
      #include <fmgr.h>
      #ifdef PG_MODULE_MAGIC
      PG_MODULE_MAGIC
      #endif
    }
    
于 2015-06-20T20:28:36.017 に答える
1

私はまだもっと良い方法があるかもしれないと確信していますが、これは私がやったことです。

(すべての bytea が 4 バイトであると仮定するのではなく、範囲チェックを追加します... 最終的に、潜在的なセグメンテーション違反を本番環境に残すことは悪いことなので、これは単なるおもちゃのプロジェクトであることは良いことです)

phash.c - gcc でコンパイルされた純粋な 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);
}

phash_wrapper.cpp - cpp リンクの代わりに c リンクを使用して ph_hamming_distance のバージョンを変換します (g++ でコンパイル)

#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

SQL - 同じ

CREATE FUNCTION phash_hamming (bytea1 bytea, bytea2 bytea) RETURNS int AS '$libdir/phash' LANGUAGE C;
于 2012-08-07T04:16:06.163 に答える