multiple definition c++/c google test - c++

So ive looked at similar issues and I followed what they said. I have made sure that my .h and .cpp file are in my main test file.
So I'm not really sure whats wrong. I fixed an earlier error like this but it was something I caught. Id appreciate some help.
Matrix-Multiply.h
Matrix-Multiply.h
#ifndef __MATRIX_MULTIPLY_H
#define __MATRIX_MULTIPLY_H
#include<stdio.h>
#include<stdlib.h>
float *expectedFinalMatrixOutput(int mA,int nA,int mB,int nB,float *matA,float *matB);
int readFiles(const char *matAFile,const char *matBFile);
#endif //__MATRIX_MULTIPLY_H
Matrix-Multiply.cpp
//.cpp file
#include<stdio.h>
#include<stdlib.h>
float *expectedFinalMatrixOutput(int mA,int nA,int mB,int nB,float *matA,float *matB)
{
int m = mA;
int n = nB;
int size = m * n;
float *finalMatrix[size];
//build both matrices
//for both the matA Column and matB Row need to be the
//same before even multiplying
//dot product matrix
//the end matrix needs the have the same number of rows as
//matA and same number of columns as matB
return *finalMatrix;
}
int readFiles(const char *matAFile,const char *matBFile)
{
int flag;
//read in file for matrixs
//set flag for whether true or false
//verify row and column being taken have actual values and
//that the sized are correct
return flag;
}
Matrix-Multiply_unittests.cpp
// tests.cpp
#include "Matrix-Multiply.h"
#include "Matrix-Multiply.cpp"
#include<gtest/gtest.h>
#include<stdio.h>
TEST(matrixSize,emptyMatrix)
{
float *matA = NULL;
float *matB = NULL;
float *matrix =
expectedFinalMatrixOutput(0,0,0,0,matA,matB);
ASSERT_EQ(*(matrix),0);
}
TEST(dotTest,oneByoneMatrix)
{
float fMatrix[1] = {1};
float sMatrix[1] = {1};
float *matrix = expectedFinalMatrixOutput(1,1,1,1,fMatrix,sMatrix);
ASSERT_EQ(matrix[0],1);
}
TEST(dotTest,twoBytwoMatrix)
{
float fMatrix[4] = {1,1,1,1};
float sMatrix[4] = {1,1,1,1};
float *matrix = expectedFinalMatrixOutput(2,2,2,2,fMatrix,sMatrix);
for(int i =0;i<4;i++)
{
EXPECT_EQ(2,matrix[i]);
}
}
TEST(ReadFilesTest,filesExist)
{
const char *matA = "../src/Matrix1_3_3.txt";
const char *matB = "../src/Matrix2_3_3.txt";
ASSERT_EQ(0,readFiles(matA,matB));
}
TEST(ReadFilesTest,filesDontExist)
{
const char *matA = "../src/notReal.txt";
const char *matB = "../src/Matrix2_3_3.txt";
ASSERT_EQ(0,readFiles(matA,matB));
}
TEST(ReadFilesTest,matrixSizeNotCompatible)
{
const char *matA = "../src/Matrix1_3_3.txt";
const char *matB = "../src/Matrix2_2_2.txt";
ASSERT_EQ(0,readFiles(matA,matB));
}
int main(int argc,char **argv)
{
testing::InitGoogleTest(&argc,argv);
return RUN_ALL_TESTS();
}
Sorry if its not all on one line. I tried to get it that way. But the error i get is:
obj/Matrix-Multiply.o: In function `expectedFinalMatrixOutput(int, int, int,
int, float*, float*)':
Matrix-Multiply.cpp:(.text+0x0): multiple definition of
`expectedFinalMatrixOutput(int, int, int, int, float*, float*)'
/tmp/ccUgZRUB.o:Matrix-Multiply_unittests.cpp:(.text+0x0): first defined
here
obj/Matrix-Multiply.o: In function `readFiles(char const*, char const*)':
Matrix-Multiply.cpp:(.text+0xbe): multiple definition of `readFiles(char
const*, char const*)'
/tmp/ccUgZRUB.o:Matrix-Multiply_unittests.cpp:(.text+0xbe): first defined
here
collect2: error: ld returned 1 exit status
make: *** [test] Error 1
Im using googletest and already make a call to make gtest
However this error occurs when i call make test.
Any help is appreciated
Makefile
CPP=g++
OBJ=obj
SRC=src
BIN=bin
CPPFLAGS=-I$(SRC)
GTEST_DIR=../googletest/googletest
gtest:
mkdir -p $(OBJ)
${CPP} -I${GTEST_DIR}/include -I${GTEST_DIR} \
-pthread -c ${GTEST_DIR}/src/gtest-all.cc -o $(OBJ)/gtest-all.o
ar -rv $(OBJ)/libgtest.a $(OBJ)/gtest-all.o
GTEST_SRCS_ = $(GTEST_DIR)/src/*.cc $(GTEST_DIR)/src/*.h $(GTEST_HEADERS)
$(OBJ)/gtest_main.o : $(GTEST_SRCS_)
$(CXX) $(CPPFLAGS) -I${GTEST_DIR}/include -I$(GTEST_DIR) $(CXXFLAGS) -c
\
$(GTEST_DIR)/src/gtest_main.cc -o $#
$(OBJ)/gtest_main.a : $(OBJ)/gtest-all.o $(OBJ)/gtest_main.o
$(AR) $(ARFLAGS) $# $^
$(OBJ)/%.o: $(SRC)/%.cpp
$(CPP) $(CPPFLAGS) $(CXXFLAGS) -c -o $# $<
.PHONY: test clean
test: $(OBJ)/Matrix-Multiply.o $(OBJ)/gtest_main.a
mkdir -p $(BIN)
$(CPP) -I${GTEST_DIR}/include $(SRC)/Matrix-Multiply_unittests.cpp \
$(OBJ)/gtest_main.a $(OBJ)/Matrix-Multiply.o -o $(BIN)/Matrix-
Multiply_unittests -pthread
$(BIN)/Matrix-Multiply_unittests
clean:
rm -f $(BIN)/*
rm -f $(OBJ)/*

I think by #include "Matrix-Multiply.cpp" you are including the functions once.
Also (although not shown), you are linking with Matrix-Multiply on the link line.
You should not normally include a .cpp file. They are better bound by linking the file.
g++ -o my_awesome_app main.o Matrix-Multiply.o otherfile.o

Related

Compilation error when including eigen library

I'm currently using eigen library, and this is the only file that I include eigen:
Kraftwerk2.cpp:
#include "Kraftwerk2.h"
Kraftwerk2::Kraftwerk2(int n){ //n: num instances
Connectivity_mat.resize(n,n);
}
int Kraftwerk2::Parse_Inst_Name(string s){ //input: String("M12"), output: int 12
return stoi(s.substr(1));
}
void Kraftwerk2::Generate_Connectivity_matrix(unordered_map<string, net> map){
for(auto& it : map){
int n =it.second.net_pin.size();
for(int i=0; i<n; i++){
for(int j=i+1; j<n; j++){
Connectivity_mat(i,j) = Connectivity_mat(i,j) +1;
}
}
}
}
void Kraftwerk2::Print_Mat(){
IOFormat CleanFmt(4, 0, ", ", "\n", "[", "]");
cout << Connectivity_mat.format(CleanFmt);
}
Kraftwerk2.h:
#include <iostream>
#include <Eigen/Core>
#include "module.h"
using namespace std;
// unordered_map<string, instance> instances;
// unordered_map<string, net> nets;
using namespace Eigen;
class Kraftwerk2{
public:
Kraftwerk2(int);
MatrixXd Connectivity_mat;
int Parse_Inst_Name(string);
void Generate_Connectivity_matrix(unordered_map<string, net>);
void Print_Mat();
};
And I use makefile for compiling:
(I'm pretty new to makefile, so if there's something I can improve, please tell me)
(Eigen is installed in the working directory ./eigen)
# CC and CFLAGS are varilables
CC = g++
CFLAGS = -c
OPTFLAGS = -O2
DBGFLAGS = -g -D_DEBUG_ON_
# make all
all : bin/partition
#echo -n "make complete!"
# optimized version
bin/partition: main_opt.o FM.o partition.o module.o Kraftwerk2.o
$(CC) $(OPTFLAGS) main_opt.o FM.o partition.o module.o Kraftwerk2.o -o bin/partition
main_opt.o: src/main.cpp src/FM_alg.h src/partition.h src/module.h src/Kraftwerk2.h
$(CC) -I ./eigen $< -o $#
FM.o: src/FM_alg.cpp src/FM_alg.h
$(CC) $(CFLAGS) $(OPTFLAGS) $< -o $#
partition.o: src/partition.cpp src/partition.h
$(CC) $(CFLAGS) $(OPTFLAGS) $< -o $#
Kraftwerk2.o: src/Kraftwerk2.cpp src/Kraftwerk2.h
$(CC) ./eigen $(CFLAGS) $(OPTFLAGS) $< -o $#
module.o: src/module.cpp src/module.h
$(CC) $(CFLAGS) $(OPTFLAGS) $< -o $#
# clean all the .o and executable files
clean:
rm -rf *.o lib/*.a lib/*.o bin/*
However, when I make, the terminal seems to output some error that comes form the library itself(???
g++ -I ./eigen src/main.cpp -o main_opt.o
In file included from ./eigen/Eigen/Core:269,
from src/Kraftwerk2.h:2,
from src/main.cpp:4:
./eigen/Eigen/src/Core/util/IndexedViewHelper.h:69:23: error: declaration of ‘template<class first> constexpr Eigen::Index Eigen::internal::first(const first&)’ shadows template parameter
69 | EIGEN_CONSTEXPR Index first(const T& x) EIGEN_NOEXCEPT { return x.first(); }
| ^~~~~
./eigen/Eigen/src/Core/util/IndexedViewHelper.h:68:10: note: template parameter ‘first’ declared here
68 | template<typename T>
| ^~~~~~~~
make: *** [makefile:15: main_opt.o] Error 1
I would be so appreciated if anybody can tell me what's wrong with this.

Cannot open a file through fopen()

Im working on making a simulator with c++, for which I need to read files.
my directory looks something like this
proj
------>bin #stores the executable
------>include #stroes the external library includefiles
------>lib #stores the lib files of the libraries
------>obj #stores the .o files
------>src #source files
makefile
my make file looks this
CC = g++
OUT = chip8
ODIR = ./obj
SDIR = ./src
OUTDIR = ./bin
IDIR = ./include
LDIR = ./lib
libs = -lmingw32 -lSDL2main -lSDL2 -lSDL2_image
OBJS = $(patsubst $(SDIR)/%.cpp,$(ODIR)/%.o,$(wildcard $(SDIR)/*.cpp))
vpath %.cpp $(SDIR):$(SDIR)/Chip8
$(ODIR)/%.o : %.cpp
$(CC) -c -I $(IDIR) -o $# $^
$(OUTDIR)/% : $(wildcard obj/*.o)
$(CC) -L $(LDIR) -o $# $^ $(libs)
.PHONY : run
run :
$(OUTDIR)/$(OUT)
these are my source files
main.cpp
#include <iostream>
#include "Chip8/RomFileReader.h"
int main(){
RomReader romReader;
if(romReader.OpenFile("picture.ch8") == -1){
std::cout<<"could not open file !"<<std::endl;
return EXIT_FAILURE;
}
romReader.GetRom();
uint8_t * rom = romReader.ReturnRom();
int size = romReader.GetRomSize();
for(int i = 0; i<size; i++)
std::cout<<rom[i]<<std::endl;
free(rom);
romReader.FreeRom();
romReader.CloseReader();
}
ReadRomFile.h
#pragma once
#include <iostream>
#include <stdlib.h>
#include <inttypes.h>
#include <stdio.h>
class RomReader{
private :
FILE * m_Reader;
uint8_t * m_Rom;
public :
int OpenFile(const char * fileName);
void GetRom();
void FreeRom();
uint8_t * ReturnRom();
void CloseReader();
int GetRomSize();
};
RomFileReader.cpp
#include "RomFileReader.h"
int RomReader :: OpenFile(const char * fileName){
m_Reader = fopen(fileName,"rb");
if(m_Reader == NULL){
return -1;
} else
return 1;
}
int RomReader :: GetRomSize(){
int start = ftell(m_Reader);
fseek(m_Reader,0,SEEK_END);
int end = ftell(m_Reader);
fseek(m_Reader,0,SEEK_SET);
int size = end - size;
return size;
}
void RomReader :: GetRom(){
int size = GetRomSize();
if(m_Rom == NULL){
m_Rom = new uint8_t[size];
}
fread(m_Rom,1,size,m_Reader);
}
void RomReader :: FreeRom(){
free(m_Rom);
}
uint8_t * RomReader :: ReturnRom(){
return m_Rom;
}
void RomReader :: CloseReader(){
fclose(m_Reader);
}
this is the error I'm getting
./bin/chip8
could not open file !
make: *** [run] Error 1
I could use fstream but I'm more comfortable and confident in using FILE instead, I had done something similar in c and it worked without any issue.
I'm really not able to point at what is exactly not working.
my picture.ch8 is in the bin folder along with the executable, yet I get this error. What is it that I'm missing exactly?
Your main is calling
romReader.FreeRom();
I think m_Rom is not NULL. So the memory get freed, so the memory exception getting fired?!?
Set it to NULL in a constructor of your class:
class RomReader {
...
public :
RomReader() { m_Rom = NULL; };
~RomReader() { if ( m_Rom != NULL ) delete [] m_Rom; };
...
}
The basic problem you have is that wildcard expands to the files that exist when make reads the makefile. So when you build with a clean tree (where the obj directory is empty), it expands to nothing, so nothing gets built.
The upshot is that wildcard cannot be usefully used with intermediate files generated as part of your build as they might not exist yet when you build. It is only useful for finding source files.
You need instead something like
$(OUTDIR)/$(OUT): $(patsubst src/%.cpp, obj/%.o, $(wildcard src/*.cpp)) $(patsubst src/Chip8/%.cpp, obj/%.o, $(wildcard src/Chip8/*.cpp))
You also probably want to have your run target depend on the executable
run: $(OUTDIR)/$(OUT)
otherwise it will not (re)build it when you try to run.

Undefined symbol when trying to link with shared library built from CUDA objects

I'm experimenting with building a simple application from a couple of .cu source files and a very simple C++ main that calls a function from one of the .cu files. I'm making a shared library (.so file) from the compiled .cu files. I'm finding that everything builds without trouble, but when I try to run the application, I get a linker undefined symbol error, with the mangled name of the .cu function I'm calling from main(). If I build a static library instead, my application runs just fine. Here's the makefile I've set up:
.PHONY: clean
NVCCFLAGS = -std=c++11 --compiler-options '-fPIC'
CXXFLAGS = -std=c++11
HLIB = libhello.a
SHLIB = libhello.so
CUDA_OBJECTS = bridge.o add.o
all: driver
%.o :: %.cu
nvcc -o $# $(NVCCFLAGS) -c -I. $<
%.o :: %.cpp
c++ $(CXXFLAGS) -o $# -c -I. $<
$(HLIB): $(CUDA_OBJECTS)
ar rcs $# $^
$(SHLIB): $(CUDA_OBJECTS)
nvcc $(NVCCFLAGS) --shared -o $# $^
#driver : driver.o $(HLIB)
# c++ -std=c++11 -fPIC -o $# driver.o -L. -lhello -L/usr/local/cuda-10.1/targets/x86_64-linux/lib -lcudart
driver : driver.o $(SHLIB)
c++ -std=c++11 -fPIC -o $# driver.o -L. -lhello
clean:
-rm -f driver *.o *.so *.a
Here are the various source files that the makefile takes as fodder.
add.cu:
__global__ void add(int n, int* a, int* b, int* c) {
int index = threadIdx.x;
int stride = blockDim.x;
for (int ii = index; ii < n; ii += stride) {
c[ii] = a[ii] + b[ii];
}
}
add.h:
extern __global__ void add(int n, int* a, int* b, int* c);
bridge.cu:
#include <iostream>
#include "add.h"
void bridge() {
int N = 1 << 16;
int blockSize = 256;
int numBlocks = (N + blockSize - 1)/blockSize;
int* a;
int* b;
int* c;
cudaMallocManaged(&a, N*sizeof(int));
cudaMallocManaged(&b, N*sizeof(int));
cudaMallocManaged(&c, N*sizeof(int));
for (int ii = 0; ii < N; ii++) {
a[ii] = ii;
b[ii] = 2*ii;
}
add<<<numBlocks, blockSize>>>(N, a, b, c);
cudaDeviceSynchronize();
for (int ii = 0; ii < N; ii++) {
std::cout << a[ii] << " + " << b[ii] << " = " << c[ii] << std::endl;
}
cudaFree(a);
cudaFree(b);
cudaFree(c);
}
bridge.h:
extern void bridge();
driver.cpp:
#include "bridge.h"
int main() {
bridge();
return 0;
}
I'm very new to cuda, so I expect that's where I'm doing something wrong. I've played a bit with using extern "C" declarations, but that just seems to move the "undefined symbol" error from run time to build time.
I'm familiar with various ways that one can end up with an undefined symbol, and I've mentioned various experiments I've already performed (static linking, extern "C" declarations) that make me think that this problem isn't addressed by the proposed duplicate question.
My unresolved symbol is _Z6bridgev
It looks to me as though the linker should be able resolve the symbol. If I can nm on driver.o, I see:
0000000000000000 T main
U _Z6bridgev
And if I run nm on libhello.so, I see:
0000000000006e56 T _Z6bridgev
When Robert Crovella was able to get my example to work on his machine, while I wasn't able to get his example to work on mine, I started realizing that my problem had nothing to do with cuda or nvcc. It was the fact that with a shared library, the loader has to resolve symbols at runtime, and my shared library wasn't in a "well-known location". I built a simple test case just now, purely with c++ sources, and repeated my failure. Once I copied libhello.so to /usr/local/lib, I was able to run driver successfully. So, I'm OK with closing my original question, if that's the will of the people.

SystemC Make Errors: Type Mismatch Member Assignment

Hello I am seeing some errors in my attempts to make a basic SystemC project. It looks like a slight mismatch of types, but I am not familiar enough with the types from the SystemC library to really know what the issue is. I have more or less taken the code directly from this tutorial.
https://www.youtube.com/watch?v=DSg4PMoUCX4
Currently, my Makefile looks like this
CXX=g++
OBJ= main.o fir_filter.o test_bench.o
INC=- -I /home/epi/jfrye_xilinx/SystemC/systemc-2.3.2/include -I /home/epi/jfrye_xilinx/SystemC/lib/fir_filter/src
LFLAGS=-L/home/epi/jfrye_xilinx/SystemC/systemc-2.3.2/lib-linux64
LIBS=-lsystemc
EXEC=test_fir
all: $(OBJ)
$(CXX) $(OBJS) -o $(EXEC)
main.o: main.cpp
$(CXX) $(INC) $(LFLAGS) $(LIBS) main.cpp
fir_filter.o: fir_filter.cpp fir_filter.h
$(CXX) $(INC) $(LFLAGS) $(LIBS) fir_filter.cpp
test_bench.o: test_bench.cpp test_bench.h
$(CXX) $(INC) $(LFLAGS) $(LIBS) test_bench.cpp
I am seeing these errors when I run make
main.cpp:28:19: error: no match for call to
(sc_core::sc_in<sc_dt::sc_uint<16> >)
(sc_core::sc_signal<sc_dt::sc_int<16> >&)
fir->inp(inp_sig);
main.cpp:29:21: error: no match for call to
(sc_core::sc_out<sc_dt::sc_uint<16> >)
(sc_core::sc_signal<sc_dt::sc_int<16> >&)
fir->outp(outp_sig);
Here is main.cpp
#include <systemc.h>
#include "fir_filter.h"
#include "test_bench.h"
SC_MODULE(SYSTEM)
{
test_bench *tb;
fir_filter *fir;
sc_signal<bool> rst_sig;
sc_signal< sc_int<16> > inp_sig;
sc_signal< sc_int<16> > outp_sig;
sc_clock clk_sig;
SC_CTOR(SYSTEM)
: clk_sig("clk_sig", 10, SC_NS)
{
tb = new test_bench("tb");
tb->clk(clk_sig);
tb->rst(rst_sig);
tb->inp(inp_sig);
tb->outp(outp_sig);
fir = new fir_filter("fir");
fir->clk(clk_sig);
fir->rst(rst_sig);
fir->inp(inp_sig);
fir->outp(outp_sig);
}
~SYSTEM()
{
delete tb;
delete fir;
}
};
SYSTEM *top = NULL;
int sc_main(int argc, char *argv[])
{
top = new SYSTEM("top");
sc_start();
return 0;
}
And lastly, fir_filter.h
#include <systemc.h>
SC_MODULE( fir_filter )
{
sc_in<bool> clk;
sc_in<bool> rst;
sc_in< sc_uint<16> > inp;
sc_out< sc_uint<16> > outp;
void fir_main();
SC_CTOR( fir_filter )
{
SC_CTHREAD( fir_main, clk.pos());
reset_signal_is( rst, true);
}
};
Update:
Thanks to the answers provided, I was able to change the two modules to ensure that the types were matching, whether signed or unsigned.
However make is still giving me this error. I did not include it originally because I did not realize it would break compilation.
g++: error: -E or -x required when input is from standard input make:
*** [main.o] Error 1
In your SYSTEM module, it shouldn't be :
sc_signal< sc_int<16> > inp_sig;
sc_signal< sc_int<16> > outp_sig;
but instead :
sc_signal< sc_uint<16> > inp_sig;
sc_signal< sc_uint<16> > outp_sig;
as inp in the FIR Filter module is a sc_in< sc_uint<16> >.

postgresql c-extension loads another external library

I need to compare pHashes (phash.org) with a hamming distance function.
I tried the one from pg_similarity, but it doesn't seem to work right. (identical pHashes don't have a hamming distance of 0).
So I figured I'd just use a c-extension to use the ph_hamming_distance function that's part of the pHash library.
What I've got:
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 that I'm getting:
ERROR: could not load library "/usr/lib/postgresql/phash.so": /usr/lib/postgresql/phash.so: undefined symbol: _Z16pg_detoast_datumP7varlena
I must not be linking right to postgresql somehow?
It's an old question, but...
There is no need to add extra wrapper file and compile it using gcc.
You need extern "C" both PostgreSQL headers and PostgreSQL macros.
extern "C" {
#include <postgres.h>
#include <fmgr.h>
#ifdef PG_MODULE_MAGIC
PG_MODULE_MAGIC
#endif
}
I'm still convinced there might be a better way but this is what I did that worked.
(I will add range-checking, instead of just assuming all bytea's are 4-bytes... eventually, leaving a potential segfault in production would be bad, so it's a good thing this is just a toy project)
phash.c - pure C file, compiled with 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);
}
phash_wrapper.cpp - make convert a version of ph_hamming_distance with c-linking instead of cpp linking (compiled with g++)
#include <pHash.h>
extern "C" {
int c_ph_hamming_distance (ulong64 b1, ulong64 b2){
return ph_hamming_distance(b1, b2);
}
}
Makefile
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 - the same
CREATE FUNCTION phash_hamming (bytea1 bytea, bytea2 bytea) RETURNS int AS '$libdir/phash' LANGUAGE C;