cyang-kth / fmm

Fast map matching, an open source framework in C++
https://fmm-wiki.github.io/
Apache License 2.0
892 stars 215 forks source link

c call c++ api segfault #230

Closed wupeaking closed 2 years ago

wupeaking commented 2 years ago

I want to call fmm c++ api using c. but I meet an issue. it always says segfault. The initial suspicion is that the smart pointer conversion error. but I don't know to fix it.

the c++ warp code:

#include <fmm/fmm-api.hpp>
#include <iostream>
#include "fmm_warp.h"
#include <fmm/mm/fmm/ubodt.hpp>
#include <fmm/mm/fmm/fmm_algorithm.hpp>
#include <fmm/python/pyfmm.hpp>

#ifdef __cplusplus
extern "C"{
#endif

using namespace FMM;
using namespace FMM::NETWORK;
using namespace FMM::CORE;
using namespace FMM::MM;

void *network_create(char* filename, char* id, char* source, char* target) {
    std::string file_str(filename);
    std::string id_str(id);
    std::string source_str(source);
    std::string target_str(target);
    return new NETWORK::Network(file_str, id_str, source_str, target_str); //构造
}

void network_delete(void* network){
    delete static_cast<NETWORK::Network *>(network);
}

int network_get_node_count(void* network) {
    return static_cast<NETWORK::Network *>(network)->get_node_count();
}

void* networkgraph_create(void* network) {
    // FMM::NETWORK::Network& p = static_cast<NETWORK::Network *>(network);
    return new NETWORK::NetworkGraph(*(static_cast<NETWORK::Network *>(network)));
}

void networkgraph_delete(void* graph) {
    delete static_cast<NETWORK::NetworkGraph *>(graph);
}

void* read_ubodt_csv(char* filename){
    std::string file_str(filename);
    std::shared_ptr<UBODT> u =  UBODT::read_ubodt_csv(file_str);
    //  UBODT &b = *u;
    // UBODT *b = &*u;
    // UBODT *b = u.get();
    return &*u;
}

void ubodt_delete(void* ubodt) {
    delete static_cast<UBODT *>(ubodt);
}

double ubodt_get_delta(void* ubodt){
    return static_cast<UBODT *>(ubodt)->get_delta();
}

void* FastMapMatch_create(void* network, void* graph, void* ubodt){
    std::shared_ptr<UBODT> ubodt_shared_ptr((UBODT* )ubodt);
    // ubodt_shared_ptr.reset((UBODT *)ubodt);
    std::cout << "FastMapMatch_create----" << std::endl;
    std::cout << ubodt_shared_ptr->get_delta() << std::endl;

    return new FastMapMatch(
        *(static_cast<NETWORK::Network *>(network)),
        *(static_cast<NETWORK::NetworkGraph *>(graph)),
        ubodt_shared_ptr
    );
}

void FastMapMatch_match_wkt(void* fmm, char* wkt, void* fmm_cfg) {
    std::cout<< "1 -----------------" << std::endl;
    std::string file_str(wkt);
    std::cout<< "2 -----------------" << std::endl;
    // PYTHON::PyMatchResult result = 
    static_cast<FastMapMatch *>(fmm)->match_wkt(
        file_str,
        *(static_cast<FastMapMatchConfig *>(fmm_cfg))
    );
    std::cout<< "3 -----------------" << std::endl;
    // SPDLOG_INFO("Matched path: {} ", result.cpath);
}

void* FastMapMatchConfig_create(int k_arg, double r_arg, double gps_error, double reverse_tolerance) {
    return new FastMapMatchConfig(k_arg, r_arg, gps_error, reverse_tolerance);
}

void FastMapMatchConfig_delete(void* fmm_cfg) {
    delete static_cast<FastMapMatchConfig *>(fmm_cfg);
}
#ifdef __cplusplus
}
#endif

the c test code:

#include "fmm_warp.h"
#include <stdio.h>

int main() {
    void* network = network_create("data/edges.shp", "id", "source", "target");
    printf("--------- %d\n", network_get_node_count(network));
    void* graph = networkgraph_create(network);
    void* ubdot = read_ubodt_csv("data/ubodt.txt");
    void* fmm = FastMapMatch_create(network, graph, ubdot);
    void* fmm_cfg = FastMapMatchConfig_create(4, 0.4, 0.5, 0);
    FastMapMatch_match_wkt(
        fmm,
        "LINESTRING(0.200812146892656 2.14088983050848,1.44262005649717 2.14879943502825,3.06408898305084 2.16066384180791,3.06408898305084 2.7103813559322,3.70872175141242 2.97930790960452,4.11606638418078 2.62337570621469)",
        fmm_cfg
    );
}
wupeaking commented 2 years ago

I have solved this problem.