HarmonyOS鸿蒙Next中团结引擎如何和DevEco Studio的C++互相通信

HarmonyOS鸿蒙Next中团结引擎如何和DevEco Studio的C++互相通信 如题,纯小白,求详细操作过程。注意是C++,不要ArkTs的

11 回复

开发者您好,请您参考以下方案:
团结引擎开发的游戏适配HarmonyOS,HarmonyOS和OpenHarmony适配的方案一致,文档入口您可以参考官网文档:团结引擎游戏的系统适配。进入之后,您可以参考文档适配指导中6 适配三方库完成。

更多关于HarmonyOS鸿蒙Next中团结引擎如何和DevEco Studio的C++互相通信的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html


  1. DevEco 编写 OpenHarmony 平台 C++ 业务代码并编译 so 库
  2. so 库导入团结引擎专属鸿蒙插件目录;
  3. 引擎 C# 通过 DllImport 直接调用 C++ 能力;
  4. C++ 需要主动推送数据时,使用 TuanjieSendMessage 回调引擎;
  5. 引擎导出鸿蒙工程,DevEco 整体构建,完成联调与真机运行。

具体可看官方资料:【团结引擎_鸿蒙游戏的新手指导】

团结引擎(Laya)与 DevEco C++ 通信实现如下

一、通信原理概述

技术栈关系

  • 团结引擎(Laya):运行在 ArkTS 层,负责游戏逻辑(JavaScript/ArkTS)
  • DevEco C++ 模块:通过 NDK 编译为 .so 动态库,提供高性能原生能力
  • 通信桥梁:使用 HarmonyOS NAPI 框架实现 ArkTS 与 C++ 的双向数据交换

关键机制

  • NAPI 接口:实现跨语言方法调用与回调
  • 序列化协议:通过 Sendable 对象实现线程安全的数据传递

二、操作步骤

步骤 1:配置 NDK 工程

创建 Native C++ 模块

在 DevEco Studio 中选择 File > New > Native C++ 模板

配置 CMakeLists.txt

确保 ABI 兼容性(如 arm64-v8a):

cmake_minimum_required(VERSION 3.4.1)
project(LayaBridge)
# 生成动态库
add_library(laya_bridge SHARED bridge.cpp)
# 链接 NAPI 库
target_link_libraries(laya_bridge PUBLIC libace_napi.z.so)

配置 build-profile.json5

声明 NDK 路径:

{
  "externalNativeOptions": {
    "path": "./src/main/cpp/CMakeLists.txt",
    "abiFilters": ["arm64-v8a"]
  }
}

步骤 2:实现 C++ 通信接口

定义跨线程回调结构体

// bridge.cpp
#include "napi/native_api.h"
#include <string>
// 定义回调函数类型
using Callback = std::function<void(const std::string&)>;
static Callback g_layaCallback; // 全局回调
// 注册 ArkTS 回调到 C++
static napi_value RegisterCallback(napi_env env, napi_callback_info info) {
    napi_value args;
    napi_get_cb_info(env, info, nullptr, nullptr, &args, nullptr);
    napi_create_reference(env, args, 1, &g_callbackRef); // 持久化引用
    return nullptr;
}

暴露 C++ 函数给 ArkTS

// 声明模块导出函数
static napi_value Init(napi_env env, napi_value exports) {
    napi_property_descriptor desc[] = {
        { "registerCallback", nullptr, RegisterCallback, nullptr, nullptr, nullptr, napi_default, nullptr }
    };
    napi_define_properties(env, exports, sizeof(desc)/sizeof(desc[0]), desc);
    return exports;
}
NAPI_MODULE(laya_bridge, Init)

步骤 3:ArkTS 层调用 C++

加载 Native 模块

// Laya 游戏代码中
import native from '@kit.ArkTS';
const nativeBridge = native.load('laya_bridge'); // 对应 CMake 中的库名
nativeBridge.registerCallback((msg: string) => {
    console.log('C++消息: ' + msg); // 接收 C++ 回调
});

触发 C++ 函数执行

// 从 Laya 引擎调用 C++ 方法
nativeBridge.invoke('calculateDistance',
    { x1: 10, y1: 20, x2: 30, y2: 40 },
    (result) => {
        console.log('计算结果: ' + result);
    }
);

步骤 4:C++ 调用 ArkTS 回调

// 在 C++ 中触发回调(如计算完成后)
static void SendToLaya(const std::string& result) {
    napi_env env = ...; // 从线程安全上下文获取 env
    napi_value callback;
    napi_get_reference_value(env, g_callbackRef, &callback);

    napi_value argv;
    napi_create_string_utf8(env, result.c_str(), result.length(), &argv);

    napi_call_function(env, nullptr, callback, 1, &argv, nullptr); // 跨线程调用
}

三、调试与验证

断点配置

  1. 在 DevEco Studio 中设置 Run/Debug Configurations > Debugger > Dual(ArkTS/JS + Native)
  2. 同时在 ArkTS 和 C++ 代码中打断点

日志查看

使用 hilog 输出 C++ 日志:

#include "hilog/log.h"
OH_LOG_Print(LOG_APP, LOG_INFO, 0, "Bridge", "C++ message sent");

四、注意事项

线程安全

  • NAPI 对象禁止跨线程直接操作
  • 需通过 napi_create_threadsafe_function 封装

数据类型映射

ArkTS 类型 C++ 类型 转换接口
number int/double napi_get_value_int32
string std::string napi_create_string_utf8
object napi_value napi_get_property

性能优化

  • 高频通信使用 Sendable 对象避免序列化开销

五、环境要求

  • 系统版本:HarmonyOS 5.0+
  • IDE 版本:DevEco Studio 5.0.4+
  • NDK 版本:建议使用最新稳定版

参考资源

  1. 【鸿蒙开发案例篇】NAPI 实现 ArkTS 与 C++ 间的复杂对象传递
  2. C/C++代码怎么调用鸿蒙应用中的ArkTS代码?
  3. 如何使用DevEco Studio进行C/C++代码断点调试
  4. 华为开发者联盟 - Native C++ 模板示例

提示:完整示例工程可参考华为开发者联盟文档中的 Native C++ 模板。若遇编译问题,请检查 NDK 版本兼容性。

开发者您好!

一、整体架构(一句话看懂)

  • 团结引擎侧:C# → P/Invoke 调用 C++ 插件(.so)
  • 鸿蒙侧(DevEco C++):通过 N-API / 动态链接 加载同一个 C++ 共享库(.so)
  • 双向通信:C++ 作为中间层,两边都能调用它;C++ 再通过 函数指针 / 回调 反向调用两边

你要的是:团结引擎 C# ↔ C++ ↔ DevEco C++(纯原生通道)


二、环境准备

  1. 安装 团结引擎(Tuanjie),并勾选 OpenHarmony Build Support 模块
  2. 安装 DevEco Studio(带 Native C++ SDK、NDK)
  3. 系统:Windows /macOS 均可;架构:arm64-v8a(鸿蒙手机 / 平板)

三、第一步:编写共用的 C++ 库(两边都调用它)

1. 新建 C++ 库项目(或直接写 .h/.cpp)

新建文件夹 SharedCpp,创建 2 个文件:

(1) shared_api.h(对外接口)

#ifndef SHARED_API_H
#define SHARED_API_H

#include <stdint.h>

// 必须加 extern "C",防止C++名称粉碎(关键!)
#ifdef __cplusplus
extern "C" {
#endif

// 1. 简单函数:C++ 加法(两边都能调用)
int32_t Shared_Add(int32_t a, int32_t b);

// 2. 回调类型:用于 C++ → 调用 C# / DevEco C++
typedef void (*SharedMessageCallback)(const char* msg);

// 3. 注册回调(C#/DevEco C++ 把自己的函数传给C++)
void Shared_RegisterCallback(SharedMessageCallback cb);

// 4. C++ 主动发消息(触发回调)
void Shared_SendMessage(const char* msg);

#ifdef __cplusplus
}
#endif

#endif // SHARED_API_H

(2) shared_api.cpp(实现)

#include "shared_api.h"

// 全局保存回调指针
static SharedMessageCallback g_Callback = nullptr;

int32_t Shared_Add(int32_t a, int32_t b) {
    return a + b;
}

void Shared_RegisterCallback(SharedMessageCallback cb) {
    g_Callback = cb;
}

void Shared_SendMessage(const char* msg) {
    if (g_Callback) {
        g_Callback(msg); // 回调:C++ → C# / DevEco C++
    }
}

四、第二步:编译 C++ 为 .so(给鸿蒙 / 团结引擎用)

方案 A:用 DevEco 编译(推荐,一次编译两边用)

  1. DevEco 新建 Native C++ 空项目
  2. 把 shared_api.h / shared_api.cpp 放入 entry/src/main/cpp/
  3. 修改 CMakeLists.txt(编译成动态库)
cmake_minimum_required(VERSION 3.13)
project(sharedcpp)

# 编译为动态库
add_library(sharedcpp SHARED
    shared_api.cpp
)

# 头文件路径
include_directories(${CMAKE_CURRENT_SOURCE_DIR})
  1. 点击 Build → Make Project
  2. 生成路径:
entry/build/intermediates/cmake/release/obj/arm64-v8a/libsharedcpp.so

方案 B:用团结引擎编译(略)

  • 放入 Assets/Plugins/OHOS/arm64-v8a/
  • 团结引擎会自动参与 NDK 编译

五、第三步:团结引擎侧(C# → C++)

1. 放入 .so 和头文件

  • 在团结引擎中创建目录:
Assets/Plugins/OHOS/arm64-v8a/libsharedcpp.so
Assets/Plugins/OHOS/include/shared_api.h
  • 选中 .so → Inspector:
    • Select Platforms: OHOS
    • CPU: ARM64
    • 勾选 Load On Startup

2. C# 调用 C++(P/Invoke)

新建脚本 NativeComm.cs

using System;
using System.Runtime.InteropServices;
using UnityEngine;

public class NativeComm : MonoBehaviour
{
    // 1. 引入共用C++库
    #if UNITY_OPENHARMONY
    const string LIB_NAME = "sharedcpp";
    #else
    const string LIB_NAME = "__Internal";
    #endif

    [DllImport(LIB_NAME, CallingConvention = CallingConvention.Cdecl)]
    private static extern int Shared_Add(int a, int b);

    [DllImport(LIB_NAME, CallingConvention = CallingConvention.Cdecl)]
    private static extern void Shared_RegisterCallback(SharedMessageCallback cb);

    [DllImport(LIB_NAME, CallingConvention = CallingConvention.Cdecl)]
    private static extern void Shared_SendMessage(string msg);

    // 2. 回调委托(匹配C++的typedef)
    [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
    public delegate void SharedMessageCallback(string msg);

    // 3. 保存委托(防止GC回收,关键!)
    private static SharedMessageCallback s_Callback;

    void Start()
    {
        // (1) C# → C++:调用加法
        int sum = Shared_Add(10, 20);
        Debug.Log($"C# 调用 C++ Add: 10+20 = {sum}");

        // (2) 注册C#回调(C++将来能调用)
        s_Callback = OnCppMessage;
        Shared_RegisterCallback(s_Callback);

        // (3) C# → C++:发消息
        Shared_SendMessage("Hello from Unity C#");
    }

    // (4) C++ → C#:回调函数
    [AOT.MonoPInvokeCallback(typeof(SharedMessageCallback))]
    static void OnCppMessage(string msg)
    {
        Debug.Log($"C# 收到 C++ 回调: {msg}");
    }
}

3. 挂载与导出

  • NativeComm 挂到场景中一个 GameObject
  • File → Build Settings → OHOS → Build
  • 导出 DevEco 工程(后面要导入 DevEco)

六、第四步:DevEco C++ 侧(鸿蒙 C++ → C++ 库)

1. 导入共用库

  1. 打开刚才团结引擎导出的 DevEco 工程
  2. libsharedcpp.so 放入:
entry/src/main/cpp/libs/arm64-v8a/
  1. shared_api.h 放入:
entry/src/main/cpp/include/

2. 修改 CMakeLists.txt(链接 .so)

cmake_minimum_required(VERSION 3.13)
project(entry)

# 1. 头文件
include_directories(include)

# 2. 库路径
link_directories(${CMAKE_CURRENT_SOURCE_DIR}/libs/arm64-v8a)

# 3. 你的模块
add_library(entry SHARED
    native.cpp
)

# 4. 链接共用C++库
target_link_libraries(entry
    sharedcpp  # 核心!
    log
)

3. DevEco C++ 调用(native.cpp)

#include <stdio.h>
#include <string>
#include "napi/native_api.h"
#include "include/shared_api.h"

// 1. 回调:C++ → DevEco C++
void CppMessageFromShared(const char* msg) {
    printf("DevEco C++ 收到 C++ 回调: %s\n", msg);
}

// 2. 导出给ArkTS的方法(演示用,你可以纯C++调用)
static napi_value DevEcoCallCpp(napi_env env, napi_callback_info info) {
    napi_value result;

    // (1) DevEco C++ → C++:调用加法
    int sum = Shared_Add(100, 200);
    printf("DevEco C++ 调用 C++ Add: 100+200 = %d\n", sum);

    // (2) 注册DevEco回调
    Shared_RegisterCallback(CppMessageFromShared);

    // (3) DevEco C++ → C++:发消息
    Shared_SendMessage("Hello from DevEco C++");

    // 返回结果给ArkTS(可选)
    napi_create_int32(env, sum, &result);
    return result;
}

// 3. N-API注册
extern "C" __attribute__((visibility("default")))
napi_value Init(napi_env env, napi_value exports) {
    napi_property_descriptor desc[] = {
        {"callCpp", nullptr, DevEcoCallCpp, nullptr, nullptr, nullptr, napi_default, nullptr}
    };
    napi_define_properties(env, exports, sizeof(desc)/sizeof(desc[0]), desc);
    return exports;
}

七、双向通信完整流程(最终效果)

  1. 启动 App
  2. Unity C# → 调用 Shared_Add(10,20)C++ → 返回 30
  3. Unity C# → 注册 OnCppMessage 回调到 C++
  4. Unity C#Shared_SendMessage("Hello Unity")C++
  5. C++ → 回调 → Unity C# 打印:Hello Unity
  6. DevEco C++ → 调用 Shared_Add(100,200)C++ → 返回 300
  7. DevEco C++ → 注册 CppMessageFromShared 回调
  8. DevEco C++Shared_SendMessage("Hello DevEco")C++
  9. C++ → 回调 → DevEco C++ 打印:Hello DevEco

真正双向:任何一边调用 Shared_SendMessage两边都会收到回调(共用同一个 C++ 库)


八、小白常见坑(必看)

  1. 必须加 extern "C"

    • 不加:C#/DevEco 找不到函数(名称粉碎)
  2. 回调必须防 GC

    • C# 用静态委托 + [MonoPInvokeCallback]
  3. .so 架构必须匹配

    • 鸿蒙真机:arm64-v8a
  4. 团结引擎导出后必须在 DevEco 重新编译

    • 直接运行会报 “库找不到”

在Unity引擎与基于DevEco Studio开发的鸿蒙应用之间进行C++通信,通常是指将您在Unity中编写或集成的C++代码,与鸿蒙应用的C++部分进行交互。这主要通过**原生插件(Native Plugins)**的方式来实现。

具体来说,您可以将C++代码编译成一个动态链接库(.so文件),然后在Unity和鸿蒙应用的C++层分别加载并调用这个库中的函数。

下面是详细的操作过程:

第一步:准备工作 - 编写通用的C++库

首先,您需要创建一个独立的C++项目,编写您希望共享的功能代码。这个库将被两端加载。

  1. 创建C++库项目

    • 在您的电脑上(例如使用Visual Studio、CLion或Code::Blocks)创建一个新的C++项目。
    • 将项目类型设置为“动态链接库”(Dynamic-Link Library),这样最终会生成一个 .dll (Windows) 或 .so (Linux/macOS) 文件。
  2. 编写C++接口

    • 在头文件(例如 MySharedLibrary.h)中定义您希望暴露给外界的函数。
    • 为了确保跨平台兼容性,建议使用标准的C风格函数(即使用 extern "C" 包裹)。
    // MySharedLibrary.h
    #ifdef __cplusplus
    extern "C" {
    #endif
    
    // 一个简单的示例函数,用于演示通信
    int32_t AddNumbers(int32_t a, int32_t b);
    
    #ifdef __cplusplus
    }
    #endif
    
  3. 实现C++函数 在对应的 .cpp 文件中实现这些函数。

    // MySharedLibrary.cpp
    #include "MySharedLibrary.h"
    
    int32_t AddNumbers(int32_t a, int32_t b) {
        return a + b;
    }
    
  4. 编译生成库文件 将项目编译成动态链接库。假设最终生成了名为 libMySharedLibrary.so 的文件。

第二步:在鸿蒙应用(DevEco Studio)中集成并调用C++库

在团结引擎(Tuanjie Engine)与 DevEco Studio 的混合开发中,C++ 代码的通信主要依赖于 Node-API (N-API)

简单来说,团结引擎底层本身就是 C++,它通过 Node-API 将接口暴露给 ArkTS/JS 层,而 DevEco 的 C++ 代码同样通过 Node-API 与 ArkTS 交互。因此,ArkTS 是两者通信的“桥梁”,而 C++ 是底层的“执行者”

以下是实现团结引擎 C++ 与 DevEco C++ 互相通信的详细操作过程:

🏗️ 核心架构原理

  1. 团结引擎侧 (C++):团结引擎将自身的 C++ 功能(如游戏逻辑、渲染控制)封装成 libtuanjie.so,并通过 Node-API 导出接口。
  2. 桥梁层 (ArkTS/JS):ArkTS 代码 import 团结引擎的 .so 库,同时也 import 你自己编写的 DevEco C++ .so 库。
  3. DevEco 侧 (C++):你编写自己的 C++ 代码,编译为 .so 库,并通过 Node-API 暴露接口给 ArkTS。

通信流向: 团结引擎 C++ <—> ArkTS (调用中转) <—> DevEco C++


🛠️ 详细操作步骤

第一步:准备 DevEco C++ 原生模块

首先,你需要在 DevEco Studio 中创建一个 C++ 原生库。

  1. 创建 C++ 文件: 在 entry/src/main/cpp 目录下创建 native_lib.cpp
  2. 编写 Node-API 代码: 你需要使用 Node-API 的标准宏来暴露函数。
// entry/src/main/cpp/native_lib.cpp
#include <node.h>
#include <node_object_wrap.h>

// 定义一个 C++ 函数,用于被 ArkTS 调用
void PrintLog(const napi_env env, napi_callback_info info) {
    // 这里写你的 C++ 逻辑,比如调用第三方 C++ SDK
    printf("DevEco C++: Received message from Tuanjie!\n");
}

// 注册模块
static napi_value Init(napi_env env, napi_value exports) {
    // 将 C++ 函数 "PrintLog" 映射为 JS/TS 可调用的 "printLog"
    napi_property_descriptor descriptors[] = {
        { "printLog", nullptr, PrintLog, nullptr, nullptr, nullptr, napi_default, nullptr }
    };
    napi_define_properties(env, exports, sizeof(descriptors) / sizeof(descriptors[0]), descriptors);
    return exports;
}

NAPI_MODULE(NODE_GYP_MODULE_NAME, Init)
  1. 配置 CMakeLists.txt: 确保你的 C++ 代码被编译成 .so 库(例如 libnative.so)。

第二步:在团结引擎/ArkTS 层进行桥接

在团结引擎导出的工程或 ArkTS 代码中,你需要同时加载团结引擎的库和你刚才写的 DevEco C++ 库。

  1. 导入库: 在 ArkTS 文件中(例如 Index.ets 或专门的桥接文件):
// 导入团结引擎的库 (通常引擎会自动处理,或者你需要显式导入)
import tuanjie from 'libtuanjie.so'; 

// 导入你自己写的 DevEco C++ 库
import nativeLib from 'libnative.so'; 

// 定义一个桥接函数
export function callNativeCppFunction() {
    console.info('ArkTS: 准备调用 DevEco C++');
    // 调用 DevEco C++ 的函数
    nativeLib.printLog();
}

第三步:从团结引擎 C++ 发起调用

这是最关键的一步。团结引擎的 C++ 代码不能直接 #include 你的 DevEco C++ 代码(因为它们编译环境不同,且运行时隔离)。必须通过 ArkTS 中转

  1. 团结引擎 C++ -> ArkTS: 在团结引擎的 C++ 代码中,你需要调用引擎提供的接口来发消息给 ArkTS。根据团结引擎的文档,通常使用 SendMessage 或类似的机制。

    假设在团结引擎 C++ 中:

    // 团结引擎 C++ 代码
    void SendDataToNative() {
        // 调用引擎暴露给 C++ 的接口,向 TS 层发送消息
        // 注意:具体函数名取决于团结引擎的版本,通常是 SendMessage 或类似的 Native 接口
        // 这里的 "OnDataReceived" 是你在 TS 层监听的回调名
        tuanjie::SendMessage("OnDataReceived", "Hello from Tuanjie C++");
    }
    
  2. ArkTS 接收并转发: 在 ArkTS 中监听团结引擎的消息,并转发给 DevEco C++。

// 监听团结引擎发来的消息
// 注意:具体监听方式需参考团结引擎文档,此处为逻辑示意
globalThis.tuanjieOnMessage = (msg) => {
    if (msg.type === "OnDataReceived") {
        console.info("ArkTS: 收到引擎消息 -> " + msg.data);
        // 收到消息后,调用 DevEco C++
        nativeLib.printLog(); 
    }
};

第四步:反向通信 (DevEco C++ -> 团结引擎 C++)

如果需要 DevEco C++ 主动通知团结引擎:

  1. DevEco C++ -> ArkTS: 在 C++ 中使用 Node-API 回调 JS。

    // native_lib.cpp
    // 这是一个异步通知的例子
    void NotifyTuanjie(napi_env env, void* data) {
        // 获取 JS 层的回调函数并调用,传递数据
        // ... (Node-API 标准回调代码)
    }
    
  2. ArkTS -> 团结引擎 C++: ArkTS 收到 C++ 回调后,调用团结引擎提供的接口。

    // ArkTS
    import tuanjie from 'libtuanjie.so';
    
    // 假设这是 DevEco C++ 的回调
    function onNativeEvent(data) {
        // 调用团结引擎接口,将数据传回引擎
        tuanjie.TuanjieSendMessage("GameLogic", "OnNativeEvent", data);
    }
    

⚠️ 关键注意事项

  1. 线程模型

    • ArkUI 线程:负责 UI 绘制,不能进行耗时操作。
    • TuanjieMain 线程:团结引擎的主线程(Worker 线程)。
    • C++ 线程:Node-API 的回调可能在后台线程触发。
    • 警告:千万不要在 DevEco C++ 的后台线程直接操作 ArkUI。如果需要更新 UI,必须通过 postMessage 回到 ArkUI 线程。
  2. 数据序列化: C++ 与 ArkTS 之间传递的数据通常限制为可序列化的类型(字符串、数字、JSON 对象)。如果需要传递大量二进制数据(如图片流),建议使用 ArrayBuffer

  3. 构建配置: 在团结引擎导出工程后,你需要将 DevEco 的 C++ 源码或编译好的 .so 放入导出工程的 entry/src/main/cpp 目录,并修改 CMakeLists.txt 将其链接进去,或者作为独立的 .so 依赖引入。

总结

不要试图让两个 C++ 代码直接“握手”。标准路径是: Tuanjie C++Tuanjie Native APIArkTSNode-APIDevEco C++

这得去团结引擎那看一下吧

  1. 导出接口 :在团结引擎(Unity)中,将需要被鸿蒙调用的C#方法封装并导出为C/C++接口。

  2. 加载与调用 :在鸿蒙应用中,使用 System.loadLibrary 加载团结引擎编译生成的动态链接库( .so 文件),然后通过C/C++函数指针直接调用这些导出的接口。

  3. 反向通信 :鸿蒙应用若需通知团结引擎,可以通过在第一步导出的接口中注册回调函数,再由团结引擎在特定时机触发该回调来实现。

可以到团结引擎官网问问

在 HarmonyOS Next 中,团结引擎(Unity)与 DevEco Studio 的 C++ 通信通过 Unity 原生插件(Native Plugin)实现。Unity 侧使用 C# 的 [DllImport][UnityEngine.Scripting.Preserve] 属性加载 C++ 动态库(.so)。C++ 代码在 DevEco Studio 中编译,利用 OHOS NAPI 或标准 C++ 接口导出函数,即可完成数据与逻辑交互。

团结引擎(Unity中国版)与DevEco Studio的C++通信,本质是通过动态库(.so)完成原生调用。在 HarmonyOS Next 上,C# 与 C++ 互操作完全依赖 NDK 导出的 C 接口,不涉及 ArkTS。

核心流程:

  1. 在 DevEco Studio 中创建 Native C++ 库工程,编写需要导出的函数并使用 extern "C" 修饰。
  2. 编译生成 .so(通常选 arm64-v8a),注意 build-profile.json5 中的 ABI 过滤。
  3. .so 放入团结引擎项目的 Assets/Plugins/OpenHarmony/libs/arm64-v8a/ 目录。
  4. 在团结引擎 C# 脚本里用 [DllImport("函数名")] 声明并调用。
  5. 需要 C++ 回调 C# 时,通过 Marshal.GetFunctionPointerForDelegate 将委托转为函数指针传入 C++,C++ 侧用 typedef void (*Callback)(...); 接收并回调。

C++ 导出示例 (MyPlugin.cpp)

#include <string>
extern "C" {
    const char* GetMessage() {
        static std::string msg = "Hello from C++";
        return msg.c_str();
    }
}

C# 调用 (Unity脚本)

using System.Runtime.InteropServices;
using UnityEngine;

public class PluginBridge : MonoBehaviour {
    [DllImport("GetMessage")]
    private static extern System.IntPtr GetMessage_Internal();

    void Start() {
        string msg = Marshal.PtrToStringAnsi(GetMessage_Internal());
        Debug.Log(msg);
    }
}

DllImport 里直接填函数名即可(无需 lib 前缀和 .so 后缀),团结引擎会在 OpenHarmony 平台自动解析。

C++ 回调示例
C# 定义委托,获取函数指针传入 C++,C++ 保存并在合适时机调用。注意生命周期,避免委托被 GC 回收。

整个过程不需要接触 ArkTS,所有通信链路均基于 C 接口。插件放置目录严格按照 OpenHarmony 子目录,团结引擎打包时会自动拷贝至对应 HAP 的 libs。

回到顶部