Unity通过NDK实现C#与C++之间的相互调用

由于一些历史遗留问题,我们项目还在使用一套C++实现的Box2D定点数的库,由于最近修改了视野算法所以需要重新打包安卓的【.so】文件,特此记录
1、关于NDK
在Android平台,C/C++需通过NDK编译成动态链接库.so文件,然后C#中通过[DllImport(“soname”)]声明后即可调用。(我们项目使用了lua作为胶水层进行调用 原理一样但是需要单独打一个lua的so文件 在安卓平台上)windows 平台运行dll即可

C#是Unity的官方推荐的开发语言。如果某些逻辑需要C++支持以提供高性能特性,或者需要C++去跟底层硬件或者操作系统级别的接口交互,那么就需要用C#去调用C++的接口。
这往往依赖动态链接。即用C++开发动态链接库,然后C#调用动态链接库里暴露的接口。

而在Android上开发动态链接库(.so文件)的方法,就是NDK开发。
NDK,全称Native Development Kit,是Android的一种开发工具包。
目前的Android开发,不再是纯粹的Java层开发,更多的会与C/C++结合,把一些重要的方和行为以及一些私密性质的东西放在C/C++中,通过NDK将其编译成.so动态库文件,放入工程中的libs目录。
2.版本
注意需要下载的版本。如果你的NDK同时也为Unity的IL2cpp服务,那就需要注意Unity对NDK的版本有硬性要求,比如2018的版本要求 NDK r16b的版本
下载地址
在这里插入图片描述
下载下来的压缩包,解压之后会得到如下目录:
在这里插入图片描述
最重要的是那个叫做 ndk-build.cmd 的脚本文件。它是一个基于make的构建脚本。查看它的源码你会发现它实际上执行的是:
在这里插入图片描述
为了能够在全局使用这个脚本,你最好将这个目录加入到环境变量中,也可以在这个目录打开cmd 看个人习惯
3.利用NDK构建.so
现在开始利用NDK构建.so文件,目的是在.so文件中暴露一个函数给C#调用。这个函数是自定义的加法函数,它会将两个整型相加,再返回结果。

class  MyClass
{public:static float AddFloat(float a, float b){return a + b;}};extern "C"
{float AddFloat(float a,float b){return MyClass::AddFloat(a,b);}
}

我们将在这个文件所在的目录下运行ndk-build.cmd,在此之前,我们还需要两个文件:Android.mk 和 Application.mk。这两个文件将包含 ndk-build 所需要的所有配置。两个文件的内容如下:
Android.mk

LOCAL_PATH := $(call my-dir)include $(CLEAR_VARS)LOCAL_MODULE    := gh_so
LOCAL_SRC_FILES := \
cs_call_c.c \
cs_call_cpp.cpp \
cpp_call_cs.h \
cpp_call_cs.cpp \
java_call_cpp.cpp \
cpp_call_java.cppinclude $(BUILD_SHARED_LIBRARY)

Application.mk

APP_STL := c++_static
APP_CPPFLAGS := -frtti -std=c++11
APP_PLATFORM := android-19
APP_CFLAGS += -Wno-error=format-security
APP_BUILD_SCRIPT := Android.mk
APP_ABI := armeabi-v7a x86

Android.mk 为 ndk-build描述了构建所需的源代码,链接库等信息。

变量描述
LOCAL_PATH这个变量描述了构建所需的源代码在当前工程中的相对位置。如果你是使用Android Studio进行开发,那源代码一般位于工程的 app/src/main/cpp 目录下。$(call my-dir) 返回Android.mk所在的目录。
CLEAR_VARS将一个特殊的Makefile文件包含进来。CLEAR_VARS定义了这个文件的位置。这个Makefile文件会清除所有之前定义过的Android.mk变量,一般都以LOCAL_开头
LOCAL_MODULEndk-build构建出来的库的名称,如果设定的名称没有以lib开头,则ndk-build会自动为你加这个前缀。例如,上面定义的名称将构建出来一个叫gh.so的库
LOCAL_C_INCLUDES当你的代码中include一些文件不在默认的搜索路径时,你可以使用这个变量去指定。一般来说,标准c头文件,和一些常见的Android头文件,都是在默认的搜索路径中的,他们都可以在你下载的NDK工具包中找得到
LOCAL_SRC_FILES需要构建的源文件(不包含头文件)都需要放到这里面
LOCAL_CFLAGS这个变量定义一些ndk-build的编译选项,一般来说,不需要额外的设置
BUILD_SHARED_LIBRARY将一个特殊的构建文件包含进来。BUILD_SHARED_LIBRARY定义了这个文件的位置。该文件会收集你在定义的所有上述LOCAL_开头的变量所包含的信息,然后确定如何从源文件中构建动态链接库。这个构建脚本要求你至少定义了LOCAL_MODULE和LOCAL_SRC_FILES两个变量。

Application.mk 为ndk-build描述了项目的构建性质。

|APP_STL | 需要使用哪些C++标准库 |
|APP_CPPFLAGS | 项目中,C++部分使用的编译选项 |
|APP_PLATFORM | 构建的Android API级别,对应于应用程序的min SDK Version |
|APP_CFLAGS | 项目中,C/C++部分使用的编译选项 |
|APP_BUILD_SCRIPT | Android.mk 文件所在的位置 |
|APP_ABI | 需要为哪些abi机器构建共享库 |

然后我们在终端输入以下命令:

ndk-build.cmd NDK_PROJECT_PATH=. NDK_APPLICATION_MK=Application.mk

在这里插入图片描述
你会得到一个libs目录和一个obj中间文件暂存目录。libs目录里面就是对应你所设置的abi平台对应的两种架构的so文件
在这里插入图片描述

将so拷贝到Unity工程中的Assets/Plugins/Android/libs目录中
将我们打包出来的.so文件放到上述的目录下。因为不同abi的共享库名称都一样,为避免冲突,我们拷贝它的任意父目录即可。无论.so存放到哪儿,Unity都会识别出这个共享库属于哪个abi平台的。项目目录结构如下
在这里插入图片描述
4.通过DllImport调用

using System.Collections;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using UnityEngine;
using UnityEngine.UI;public class CsCallCCPP_DllImport_SO : MonoBehaviour
{public Text txt;public Button btn1;public Button btn2;void Start(){btn1.onClick.AddListener(() => {//C#调用Ctxt.text = "C#调用C接口: AddInt(2, 6) = " + AddInt(2, 6);});btn2.onClick.AddListener(() => {//C#调用C++txt.text = "C#调用C++接口: AddFloat(2.7, 4.2) = " + AddFloat(2.7f, 4.2f);});}//C接口[DllImport("gh_so")]public static extern int AddInt(int a, int b);//C++接口[DllImport("gh_so")]public static extern float AddFloat(float a, float b);
}

5.打包调用
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/43242.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【渗透测试】利用hook技术破解前端JS加解密 - JS-Forward

前言 在做渗透测试项目时,尤其是金融方面,经常会遇到前端JS加解密技术,看着一堆堆密密麻麻的密文,会给人一种无力感。Hook技术则会帮助我们无需获取加解密密钥的前提下,获取明文进行渗透测试 环境准备 JS-Forward Burp…

城市地下综合管廊物联网远程监控

城市地下综合管廊物联网远程监控 城市地下综合管廊,作为现代都市基础设施的重要组成部分,其物联网远程监控系统的构建是实现智慧城市建设的关键环节。这一系统集成了先进的信息技术、传感器技术、通信技术和数据处理技术,旨在对埋设于地下的…

sql 清空表,并清空自增 id

执行 sql TRUNCATE 表名 表名替换为自己要清空的表 在 Navicat 中 新建查询输入 上述 sql点击运行即可表页 f5 刷新,数据已经清空,再次新增数据,自增 id 从 1 开始

Tomcat的负载均衡、动静分离

一、如何tomcat和nginx负载均衡及动静分离:2台tomcat,3台nginx来实现 1.首先设置tomcat1和tomcat2服务器 关闭两台tomcat的防火墙及安全机制:systemctl stop filwalld setenforce 0 进入tomcat目录的webapps中,创建test 2.配…

音频demo:使用opencore-amr将PCM数据与AMR-NB数据进行相互编解码

1、README a. 编译 编译demo 由于提供的.a静态库是在x86_64的机器上编译的,所以仅支持该架构的主机上编译运行。 $ make编译opencore-amr 如果想要在其他架构的CPU上编译运行,可以使用以下命令(脚本)编译opencore-amr[下载地…

移除元素合并两个有序数组-LeetCode

一、移除元素 . - 力扣&#xff08;LeetCode&#xff09; 题目描述&#xff1a; int removeElement(int* nums, int numsSize, int val) {int src0;int dst0;while(src<numsSize){if(nums[src]val){src;}else if (nums[src]!val){nums[dst]nums[src];src;dst;}}return dst…

渲染引擎之ECS架构介绍

1.什么是ECS&#xff1f; 我们先简单地介绍一下什么是ECS&#xff1a; E -- Entity 实体&#xff0c;本质上是存放组件的容器C -- Component 组件&#xff0c;引擎所需的所有数据结构S -- System 系统&#xff0c;根据组件数据处理逻辑状态的管理器 ECS全称Entity-Component-…

SAPUI5基础知识11 - 组件配置(Component)

1. 背景 组件&#xff08;Component&#xff09;是SAPUI5应用程序中独立且可重用的部件。 SAPUI5提供以下两类组件: faceless组件 (class: sap.ui.core.Component): 无界面组件即没有用户界面相关的元素&#xff0c;用于不需要UI元素编码的场景&#xff1b; UI组件 (class: …

C# 实现基于exe内嵌HTTPS监听服务、从HTTP升级到HTTPS 后端windows服务

由于客户需要把原有HTTP后端服务升级为支持https的服务&#xff0c;因为原有的HTTP服务是一个基于WINDOWS服务内嵌HTTP监听服务实现的&#xff0c;并不支持https, 也不像其他IIS中部署的WebAPI服务那样直接加载HTTPS证书&#xff0c;所以这里需要修改原服务支持https和服务器环…

JAVA进阶学习11

文章目录 一、方法引用1.1 引用静态方法1.2 引用成员方法1.3 引用构造方法1.4 方法引用的其他调用方式1.4.1 使用类名引用成员方法1.4.2 引用数组的构造方法 1.5 总结二、异常2.1 异常的处理2.1.1 JVM虚拟机处理异常2.1.2 try...catch异常处理 2.2 异常中的常见方法2.3 异常的抛…

Java集合升序降序、转Set的方法

Collections.sort(list,Comparator.comparing(OcApplySquareVo::getApplyName).reversed()); 集合转set /** 集合转set */Set<String> pkCodeSet rows.stream().map(RailwayWeighBookResult.RailwayWeighBook::getPkCode).collect(Collectors.toSet());

互联网接入技术的简单介绍

引言 要连接到互联网&#xff0c;用户必须先连接到某个ISP&#xff08;互联网服务提供商&#xff09;。接入技术解决的就是用户如何连接到本地ISP的问题&#xff0c;通常称之为“最后一公里”。本文将详细介绍几种主要的互联网接入技术&#xff0c;帮助初学者了解不同的接入方…

【SOM神经网络的数据分类】SOM神经网络的数据分类的一个小案例

【SOM神经网络的数据分类】SOM神经网络的数据分类的一个小案例 注&#xff1a;本文仅作为自己的学习记录以备以后复习查阅 一 概述 自组织特征映射网络&#xff08;Self-Organizing Feature Map, SOM&#xff09;也叫做Kohonen网络&#xff0c;它的特点是&#xff1a;全连接、…

【C++深度探索】继承机制详解(二)

hello hello~ &#xff0c;这里是大耳朵土土垚~&#x1f496;&#x1f496; &#xff0c;欢迎大家点赞&#x1f973;&#x1f973;关注&#x1f4a5;&#x1f4a5;收藏&#x1f339;&#x1f339;&#x1f339; &#x1f4a5;个人主页&#xff1a;大耳朵土土垚的博客 &#x1…

如何把已经上传到gitlab的代码或者文件夹从git上删掉

有小伙伴不小心把缓存文件上传到了git&#xff0c;跑来问我&#xff0c;要怎么把这些文件给删掉&#xff0c;这里一共有两种方式&#xff0c; 先说第一种&#xff0c;通过命令删除&#xff0c;终端进入存在这个缓存文件的目录&#xff0c;执行命令ls&#xff0c;可以看到确实有…

从零开始搭建vite开发环境

准备 nodejs 18 pnpm https://vitejs.cn/ 开始 pnpm init pnpm add -D vite新建index.html <!DOCTYPE html> <html lang"zh"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width…

飞睿智能无线高速uwb安全数据传输模块,低功耗、抗干扰超宽带uwb芯片传输速度技术新突破

在信息化的时代&#xff0c;数据传输的速度和安全性无疑是每个企业和个人都极为关注的话题。随着科技的飞速发展&#xff0c;超宽带&#xff08;Ultra-Wideband&#xff0c;简称UWB&#xff09;技术凭借其性能和广泛的应用前景&#xff0c;逐渐成为了数据传输领域的新星。今天&…

JavaScript学习笔记(七)

45.9 JavaScript 可迭代对象 可迭代对象&#xff08;Iterables&#xff09;是可以使用 for..of 进行迭代的对象。 从技术上讲&#xff0c;可迭代对象必须实现 Symbol.iterator 方法。 45.9.1 遍历字符串 <body><p id"demo"></p><script>c…

使用vllm部署大语言模型

vLLM是一个快速且易于使用的库&#xff0c;用于LLM&#xff08;大型语言模型&#xff09;推理和服务。通过PagedAttention技术&#xff0c;vLLM可以有效地管理注意力键和值内存&#xff0c;降低内存占用和提高计算效率。vLLM能够将多个传入的请求进行连续批处理&#xff0c;从而…

PTrade常见问题系列5

回测失败&#xff1a;可用资源不足。 回测运行失败&#xff0c;错误码&#xff1a;2 错误信息&#xff1a;可用资源不足&#xff0c;请稍后在创建。 1、之前客户未限制客户容器使用内存和CPU&#xff0c;周末修改配置&#xff0c;限制了内存和CPU&#xff1b; 2、此报错是用户…