c注册cpp回调函数

在C语言中注册回调函数,函数需要使用静态函数,可使用bind和function来转换

案例一:

#include <iostream>
#include <functional>
#include <string.h>
#include "http_server.h"
#include "ret_err_code.h"
#include "log_api.h"

#include "file_transfer.h"
#include "request_reprogram.h"
#include "request_progress.h"

#define PORT "8089"
#define HOST_INFO "http://localhost:8089"

#define FILE_TRANSFER "/path/a"
#define REQUEST_REPROGRAM "/path/b"
#define REQUEST_PROGRESS "/path/c"

std::mutex HttpServer::mtx;
HttpServer *HttpServer::instance = nullptr;
std::function<int32_t(struct mg_connection *conn, void *cbdata)> EcuFileTransferHandler;
std::function<int32_t(struct mg_connection *conn, void *cbdata)> RequestReprogramHandler;
std::function<int32_t(struct mg_connection *conn, void *cbdata)> RequestProgressHandler;

extern "C" {
    int32_t EcuFileTransferHandlerWrapper(struct mg_connection *conn, void *cbdata) {
        if (EcuFileTransferHandler) {
            return EcuFileTransferHandler(conn, cbdata);
        }
        return RET_OK;
    }
    int32_t RequestReprogramHandlerWrapper(struct mg_connection *conn, void *cbdata) {
        if (RequestReprogramHandler) {
            return RequestReprogramHandler(conn, cbdata);
        }
        return RET_OK;
    }
    int32_t RequestProgressHandlerWrapper(struct mg_connection *conn, void *cbdata) {
        if (RequestProgressHandler) {
            return RequestProgressHandler(conn, cbdata);
        }
        return RET_OK;
    }
}

HttpServer::HttpServer()
{
    EcuFileTransferHandler = std::bind(&EcuFileTransfer::EcuFileTransferHandler, EcuFileTransfer::GetInstance(), std::placeholders::_1, std::placeholders::_2);
    RequestReprogramHandler = std::bind(&RequestReprogram::RequestReprogramHandler, RequestReprogram::GetInstance(), std::placeholders::_1, std::placeholders::_2);
    RequestProgressHandler = std::bind(&RequestProgress::RequestProgressHandler, RequestProgress::GetInstance(), std::placeholders::_1, std::placeholders::_2);
}

HttpServer* HttpServer::GetInstance(void)
{
    if (instance == nullptr) {
        std::lock_guard<std::mutex> lock(mtx);
        if (instance == nullptr) {
            instance = new HttpServer;
        }
    }

    return instance;
}

void HttpServer::DelInstance(void)
{
    std::lock_guard<std::mutex> lock(mtx);
    if (instance) {
        delete instance;
        instance = nullptr;
    }
}

int32_t HttpServer::SetSourcePackagePath(string path)
{
    sourcePackagePath = path;
    return RET_OK;
}

int32_t HttpServer::SetTargetPackagePath(string path)
{
    targetPackagePath = path;
    return RET_OK;
}

static int LogMessage(const struct mg_connection *conn, const char *message)
{
	puts(message);
    return RET_OK;
}

int32_t HttpServer::Init()
{
    EcuFileTransfer::GetInstance()->SetSourcePackagePath(sourcePackagePath);
    EcuFileTransfer::GetInstance()->SetTargetPackagePath(targetPackagePath);

    const char *options[] = {"listening_ports",
                                PORT,
                                "request_timeout_ms",
                                "10000",
                                "error_log_file",
                                "error.log",
                                "enable_auth_domain_check",
                                "no",
                                0};

    int err = 0;
    /* Check if libcivetweb has been built with all required features. */
    mg_init_library(MG_FEATURES_DEFAULT);
    if (err) {
        LOG_ERR("Cannot start CivetWeb - inconsistent build.\n");
        return RET_EINVAL;
    }

    /* Callback will print error messages to console */
    memset(&callbacks, 0, sizeof(callbacks));
    callbacks.log_message = LogMessage;

    /* Start CivetWeb web server */
    ctx = mg_start(&callbacks, 0, options);
    if (ctx == nullptr) {
		LOG_ERR("Cannot start CivetWeb - mg_start failed.");
        return RET_EINVAL;
    }

	/* OTA-MASTER HTTP SERVER */
	mg_set_request_handler(ctx, FILE_TRANSFER, EcuFileTransferHandlerWrapper, 0);
    mg_set_request_handler(ctx, REQUEST_REPROGRAM, RequestReprogramHandlerWrapper, 0);
    mg_set_request_handler(ctx, REQUEST_PROGRESS, RequestProgressHandlerWrapper, 0);

    return RET_OK;
}

int32_t HttpServer::Deinit()
{
	/* Stop the server */
    mg_stop(ctx);
    return RET_OK;
}

案例二:

#include <iostream>
#include <stdlib.h>
#include <string>
#include <cstring>
#include <unistd.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <dirent.h>
#include <functional>
#include "file_transfer.h"
#include "ret_err_code.h"
#include "cJSON.h"
#include "def_databus.h"

std::mutex EcuFileTransfer::mtx;
EcuFileTransfer *EcuFileTransfer::instance = nullptr;
std::function<int32_t(const char *key, const char *filename, char *path, size_t pathlen, void *user_data)> FieldFound;
std::function<int32_t(const char *key, const char *value, size_t valuelen, void *user_data)> FieldGet;
std::function<int32_t(const char *path, long long file_size, void *user_data)> FieldStore;

extern packagesListInfo ServerPackListInfo;

extern "C" {
    int32_t FieldFoundWrapper(const char *key, const char *filename, char *path, size_t pathlen, void *user_data) {
        if (FieldFound) {
            return FieldFound(key, filename, path, pathlen, user_data);
        }
        return RET_OK;
    }

    int32_t FieldGetWrapper(const char *key, const char *value, size_t valuelen, void *user_data) {
        if (FieldGet) {
            return FieldGet(key, value, valuelen, user_data);
        }
        return RET_OK;
    }

    int32_t FieldStoreWrapper(const char *path, long long file_size, void *user_data) {
        if (FieldStore) {
            return FieldStore(path, file_size, user_data);
        }
        return RET_OK;
    }
}

static int SendJSON(struct mg_connection *conn, cJSON *json_obj)
{
	char *json_str = cJSON_PrintUnformatted(json_obj);
	size_t json_str_len = strlen(json_str);

	/* Send HTTP message header */
	mg_send_http_ok(conn, "application/json; charset=utf-8", json_str_len);

	/* Send HTTP message content */
	mg_write(conn, json_str, json_str_len);

	/* Free string allocated by cJSON_Print* */
	cJSON_free(json_str);

	return (int)json_str_len;
}

EcuFileTransfer::EcuFileTransfer()
{
    FieldFound = std::bind(&EcuFileTransfer::field_found, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, std::placeholders::_4, std::placeholders::_5);
    FieldGet = std::bind(&EcuFileTransfer::field_get, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, std::placeholders::_4);
    FieldStore = std::bind(&EcuFileTransfer::field_store, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3);
}

EcuFileTransfer* EcuFileTransfer::GetInstance(void)
{
    if (instance == nullptr) {
        std::lock_guard<std::mutex> lock(mtx);
        if (instance == nullptr) {
            instance = new EcuFileTransfer;
        }
    }

    return instance;
}

void EcuFileTransfer::DelInstance(void)
{
    std::lock_guard<std::mutex> lock(mtx);
    if (instance) {
        delete instance;
        instance = nullptr;
    }
}

int32_t EcuFileTransfer::SetSourcePackagePath(string path)
{
    sourcePackagePath = path;
    return RET_OK;
}

int32_t EcuFileTransfer::SetTargetPackagePath(string path)
{
    targetPackagePath = path;
    return RET_OK;
}


int32_t EcuFileTransfer::field_found(const char *key, const char *filename, char *path, size_t pathlen, void *user_data)
{
    if (strcmp(key, "file")) {
        return MG_FORM_FIELD_STORAGE_GET;
    }

    strcat(path, file->GetFilePath().c_str());
    if (access(path, 0) == -1) {
        int flag = mkdir(path, S_IRWXU);
        if (flag != 0) {
            std::cout << "Fail to create directory. errno " << errno << std::endl;
        }
    }

    strcat(path, "/");
    strcat(path, filename);
    return MG_FORM_FIELD_STORAGE_STORE;
}

int32_t EcuFileTransfer::field_get(const char *key, const char *value_untruncated, size_t valuelen, void *user_data)
{
	/* Copy the untruncated value, so string compare functions can be used. */
	/* The check unit test library does not have build in memcmp functions. */

    if (!strcmp(key, "uuid")) {
        string item = string(value_untruncated, valuelen);
        file->SetUuid(item);
    } else if (!strcmp(key, "ecuId")) {
        string item = string(value_untruncated, valuelen);
        file->SetEcuId(string(item));
    } else if (!strcmp(key, "ecuSoftCode")) {
        string item = string(value_untruncated, valuelen);
        file->SetEcuSoftCode(string(item));
    } else if (!strcmp(key, "ecuSoftVer")) {
        string item = string(value_untruncated, valuelen);
        file->SetEcuSoftVer(string(item));
    } else if (!strcmp(key, "packageType")) {
        string item = string(value_untruncated, valuelen);
        file->SetPackageType(string(item));
    } else if (!strcmp(key, "fileMd5")) {
        string item = string(value_untruncated, valuelen);
        file->SetFileMd5(string(item));
        file->SetFilePath(string(item));
    } else if (!strcmp(key, "packageCount")) {
        string item = string(value_untruncated, valuelen);
        file->SetPackageCount(string(item));
    } else if (!strcmp(key, "packageNum")) {
        string item = string(value_untruncated, valuelen);
        file->SetPackageNum(string(item));
    } else if (!strcmp(key, "fileCount")) {
        string item = string(value_untruncated, valuelen);
        file->SetFileCount(string(item));
    } else if (!strcmp(key, "fileNum")) {
        string item = string(value_untruncated, valuelen);
        file->SetFileNum(string(item));
    } else {}

	return RET_OK;
}


int32_t EcuFileTransfer::field_store(const char *path, long long file_size, void *user_data)
{
    file->SetStoreSuccess(true);
	return RET_OK;
}

int32_t EcuFileTransfer::EcuFileTransferHandler(struct mg_connection *conn, void *cbdata)
{
    const struct mg_request_info *ri = mg_get_request_info(conn);
    (void)cbdata; /* currently unused */

    if (0 != strcmp(ri->request_method, "POST")) {
        /* this is not a POST request */
        mg_send_http_error(conn, 405, "Only post method");
        return 405;
    }

    if (file == nullptr) {
        file = new EcuFile();
    }

    struct mg_form_data_handler fdh = {FieldFoundWrapper,
                                        FieldGetWrapper,
                                        FieldStoreWrapper,
                                        NULL};
    fdh.user_data = nullptr;
    string status = "100";

    /* Call the form handler */
    int ret = mg_handle_form_request(conn, &fdh);
    if (ret <= 0) {
        std::cout << "no any elem" << std::endl;
    }

    int32_t fl = atoi(file->GetFileCount().c_str());
    int32_t fr = atoi(file->GetFileNum().c_str());
    int32_t pl = atoi(file->GetPackageCount().c_str());
    int32_t pr = atoi(file->GetPackageNum().c_str());

    if (fl == fr) {
        string cmd = "cd " + file->GetFilePath() +
                     " &&" + " cat * > update.zip" +
                     " && mkdir -p " + targetPackagePath +
                     " && unzip -o update.zip -d " + targetPackagePath +
                     " && rm update.zip" +
                     " && cd .." +
                     " && rm -r " + file->GetFilePath();

        FILE *fp = popen(cmd.c_str(), "r");
        if(fp == NULL) {
            perror("popen error");
        }
        pclose(fp);

        if (file->GetStoreSuccess()) {
            bool repeat = false;
            size_t size = ServerPackListInfo.packInfo.size();
            for(size_t i = 0; i < size; i++) {
                string id = ServerPackListInfo.packInfo.at(i).ecuId;
                if (!id.compare(file->GetEcuId())) {
                    repeat = true;
                }
            }

            if (!repeat) {
                struct packagesInfo info;
                info.ecuId = file->GetEcuId();
                info.ecuSoftCode = file->GetEcuSoftCode();
                info.ecuSoftVer = file->GetEcuSoftVer();
                info.packagePath = targetPackagePath;
                info.packageType = file->GetPackageType();
                ServerPackListInfo.packInfo.push_back(info);
                ServerPackListInfo.packageCount = ServerPackListInfo.packInfo.size();
                ServerPackListInfo.batchUpdateFlag = false;
                ServerPackListInfo.packlistStatus = 1;
                ServerPackListInfo.batchId = "0.0.0";
                ServerPackListInfo.CreateTime = 0;
            }
        }

        if (pl == pr) {
            status = "200";
        }
    }

    if (file != nullptr) {
        delete file;
        file = nullptr;
    }

    cJSON *obj = cJSON_CreateObject();
    if (!obj) {
        /* insufficient memory? */
        mg_send_http_error(conn, 500, "Server error");
        return 500;
    }

    cJSON_AddStringToObject(obj, "status", status.c_str());
    SendJSON(conn, obj);
    cJSON_Delete(obj);

    return 200;
}


int32_t EcuFile::SetUuid(string id)
{
    uuid = id;
    return RET_OK;
}

int32_t EcuFile::SetEcuId(string id)
{
    ecuId = id;
    return RET_OK;
}

int32_t EcuFile::SetEcuSoftCode(string code)
{
    ecuSoftCode = code;
    return RET_OK;
}

int32_t EcuFile::SetEcuSoftVer(string ver)
{
    ecuSoftVer = ver;
    return RET_OK;
}

int32_t EcuFile::SetPackageType(string type)
{
    packageType = type;
    return RET_OK;
}

int32_t EcuFile::SetFileMd5(string md5)
{
    fileMd5 = md5;
    return RET_OK;
}

int32_t EcuFile::SetPackageCount(string cnt)
{
    packageCount = cnt;
    return RET_OK;
}

int32_t EcuFile::SetPackageNum(string num)
{
    packageNum = num;
    return RET_OK;
}

int32_t EcuFile::SetFileCount(string cnt)
{
    fileCount = cnt;
    return RET_OK;
}

int32_t EcuFile::SetFileNum(string num)
{
    fileNum = num;
    return RET_OK;
}

int32_t EcuFile::SetFilePath(string path)
{
    filePath = path.substr(0, 8);
    return RET_OK;
}

int32_t EcuFile::SetStoreSuccess(bool success)
{
    storeSuccess = success;
    return RET_OK;
}

string EcuFile::GetUuid()
{
    return uuid;
}

string EcuFile::GetEcuId()
{
    return ecuId;
}

string EcuFile::GetEcuSoftCode()
{
    return ecuSoftCode;
}

string EcuFile::GetEcuSoftVer()
{
    return ecuSoftVer;
}

string EcuFile::GetPackageType()
{
    return packageType;
}

string EcuFile::GetFileMd5()
{
    return fileMd5;
}

string EcuFile::GetPackageCount()
{
    return packageCount;
}

string EcuFile::GetPackageNum()
{
    return packageNum;
}

string EcuFile::GetFileCount()
{
    return fileCount;
}

string EcuFile::GetFileNum()
{
    return fileNum;
}

string EcuFile::GetFilePath()
{
    return filePath;
}

bool EcuFile::GetStoreSuccess()
{
    return storeSuccess;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
JNI(Java Native Interface)是Java提供的一种机制,用于实现Java与其他编程语言(如C++)之间的交互。C++11是C++语言的一个版本,引入了许多新的特性和改进。 在JNI中,可以通过函数实现Java与C++之间的双向通信。有返值的函数可以在C++中执行某些操作,并将结果返给Java。 以下是使用JNI和C++11实现有返值的函数的步骤: 1. 在Java中定义一个接口,用于声明函数的方法。例如: ```java public interface Callback { int callbackMethod(); } ``` 2. 在C++中实现该接口,并将其注册到JNI中。例如: ```cpp #include <jni.h> extern "C" { JNIEXPORT void JNICALL Java_com_example_MyClass_registerCallback(JNIEnv* env, jobject obj, jobject callbackObj); JNIEXPORT jint JNICALL Java_com_example_MyClass_nativeMethod(JNIEnv* env, jobject obj); } jobject gCallbackObj; JNIEXPORT void JNICALL Java_com_example_MyClass_registerCallback(JNIEnv* env, jobject obj, jobject callbackObj) { gCallbackObj = env->NewGlobalRef(callbackObj); } JNIEXPORT jint JNICALL Java_com_example_MyClass_nativeMethod(JNIEnv* env, jobject obj) { jclass callbackClass = env->GetObjectClass(gCallbackObj); jmethodID callbackMethod = env->GetMethodID(callbackClass, "callbackMethod", "()I"); jint result = env->CallIntMethod(gCallbackObj, callbackMethod); return result; } ``` 3. 在Java中用C++的函数。例如: ```java public class MyClass { static { System.loadLibrary("mylibrary"); } private native void registerCallback(Callback callback); private native int nativeMethod(); public static void main(String[] args) { MyClass myClass = new MyClass(); myClass.registerCallback(new Callback() { @Override public int callbackMethod() { // 执行某些操作并返结果 return 42; } }); int result = myClass.nativeMethod(); System.out.println("Result: " + result); } } ``` 以上代码演示了如何在Java中注册函数,并在C++中用该函数并获取返值。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值