2015-07-17 26 views
7

Sto cercando di associare i programmi C++ OpenCV con Go. Sto usando il concetto da How do you statically link a c library in go using cgo? [1]. Il mio file myimgcom.cpp è:Collegamento di C++ con Go

/** 
* @file SURF_FlannMatcher 
* @brief SURF detector + descriptor + FLANN Matcher 
* @author A. Huaman 
Edited: nnnnn 
*/ 

#include <stdio.h> 
#include <string> 
#include <iostream> 
#include "opencv2/core/core.hpp" 
#include "opencv2/features2d/features2d.hpp" 
#include "opencv2/highgui/highgui.hpp" 
#include "opencv2/nonfree/features2d.hpp" 

using namespace cv; 

void readme(); 

int mysurf(int myarg) 
{ 

string option1= "./Lenna.png"; 
string option2= "./Lenna.png"; 

if(myarg != 3) 
{ readme(); return -1; } 

std::cout << option1 << option2; 

Mat img_1 = imread(option1, CV_LOAD_IMAGE_GRAYSCALE); 
Mat img_2 = imread(option2, CV_LOAD_IMAGE_GRAYSCALE); 

if(!img_1.data || !img_2.data) 
{ std::cout<< " --(!) Error reading images " << std::endl; return -1; } 

//-- Step 1: Detect the keypoints using SURF Detector 
int minHessian = 400; 

SurfFeatureDetector detector(minHessian); 

std::vector<KeyPoint> keypoints_1, keypoints_2; 

detector.detect(img_1, keypoints_1); 
detector.detect(img_2, keypoints_2); 

//-- Step 2: Calculate descriptors (feature vectors) 
SurfDescriptorExtractor extractor; 

Mat descriptors_1, descriptors_2; 

extractor.compute(img_1, keypoints_1, descriptors_1); 
extractor.compute(img_2, keypoints_2, descriptors_2); 

//-- Step 3: Matching descriptor vectors using FLANN matcher 
FlannBasedMatcher matcher; 
std::vector<DMatch> matches; 
matcher.match(descriptors_1, descriptors_2, matches); 

double max_dist = 0; double min_dist = 100; 

//-- Quick calculation of max and min distances between keypoints 
for(int i = 0; i < descriptors_1.rows; i++) 
{ double dist = matches[i].distance; 
    if(dist < min_dist) min_dist = dist; 
    if(dist > max_dist) max_dist = dist; 
} 

    printf("-- Max dist : %f \n", max_dist); 
    printf("-- Min dist : %f \n", min_dist); 

    std::vector<DMatch> good_matches; 

    for(int i = 0; i < descriptors_1.rows; i++) 
    { if(matches[i].distance <= max(4*min_dist, 0.02)) 
    { good_matches.push_back(matches[i]); } 
    } 

    //-- Draw only "good" matches 
    Mat img_matches; 
    drawMatches(img_1, keypoints_1, img_2, keypoints_2, 
      good_matches, img_matches, Scalar::all(-1), Scalar::all(-1), 
      vector<char>(), DrawMatchesFlags::NOT_DRAW_SINGLE_POINTS); 

    //-- Show detected matches 
    imshow("Good Matches", img_matches); 

    for(int i = 0; i < (int)good_matches.size(); i++) 
    { printf("-- Good Match [%d] Keypoint 1: %d -- Keypoint 2: %d \n", i, good_matches[i].queryIdx, good_matches[i].trainIdx); } 

    waitKey(0); 

    return 0; 
} 


void readme() 
{ std::cout << " Usage: ./SURF_FlannMatcher <img1> <img2>" << std::endl; } 

successivo, il mio file di intestazione myimgcom.h file è:

int mysurf(int); 
void readme(); 

successivo, il mio file imagetest.go è:

package main 

import "fmt" 

// #include "myimgcom.h" 
import "C" 

func main() { 

    fmt.Printf("Invoking c library...\n") 
    C.mysurf(3) 

} 

sto facendo i seguenti comandi:

gcc -O2 -c myimgcom.cpp -> runs successfully 
ar q libgb.a myimgcom.o -> runs successfully 
go build imagetest.go -> Here I get the following error: 

# command-line-arguments 
Undefined symbols for architecture x86_64: 
"_mysurf", referenced from: 
    __cgo_8db0969da00f_Cfunc_mysurf in imagetest.cgo2.o 
(maybe you meant: __cgo_8db0969da00f_Cfunc_mysurf) 
ld: symbol(s) not found for architecture x86_64 
clang: error: linker command failed with exit code 1 (use -v to see invocation) 

Penso che il problema sia il collegamento tra pkg config e cflags con cgo. Qualcuno mi può suggerire come posso risolvere il problema? Sto lavorando con Mac OS.

risposta

2

C++ non è C e le convenzioni di chiamata sono diverse. È quasi impossibile chiamare direttamente il C++. Se vuoi chiamarlo da Go, prima fai un wrapper C. Nel tuo caso aggiungendo "extern C" alle dichiarazioni delle funzioni dovrebbe funzionare.

extern "C" 
int mysurf(int myarg) 
{ 
// code here 
} 
+0

Bene, quasi. Dovrebbe _declare_ 'mysurf()' come 'extern" C "' e quindi è possibile definirlo in qualsiasi modo sia necessario – user3159253