C++ —> C api —> 打包—> C# 脚本
c api 头文件
// C api header
#ifndef Bridge_hpp
#define Bridge_hpp
#include
typedef struct People {
int age;
const char *name;
} People;
typedef struct PeopleList {
People people1;
People people2;
} PeopleList;
typedef struct Peoples {
int count;
People *people;
} Peoples;
typedef void(*Func_Pointer)(int, bool, const char*);
Func_Pointer callback1, callback2;
/**
Api test.
*/
extern "C" int startLogService();
extern "C" int getSumValue(int value1, int value2);
extern "C" int setPeople(People people);
extern "C" int modifyPeople(People *people);
extern "C" int setPeopleList(PeopleList peopleList);
extern "C" int modifyPeopleList(PeopleList *peopleList);
extern "C" int setPeoples(Peoples peoples);
extern "C" int modifyPeoples(Peoples *peoples);
extern "C" void initCallback(Func_Pointer funcPointer, Func_Pointer funcPointer2);
extern "C" void testCallback();
#endif /* Bridge_hpp */
c api 实现文件:
#include "Bridge.hpp"
#include "LogHelper.h"
#ifndef __cplusplus
extern "C"
#endif
/**
Api call sample.
*/
LogHelper& logger = LogHelper::getInstance();;
int startLogService() {
logger.startLogService("./wrapper_log.txt");
return 100;
}
int getSumValue(int value1, int value2) {
return value1 + value2;
}
int setPeople(People people) {
logger.writeLog("Call setPeople from C#: age: %d, name: %s\r\n", people.age, people.name);
return 100;
}
int modifyPeople(People *people) {
logger.writeLog("Call modfiyPeople from C#: age: %d, name: %s\r\n", people->age, people->name);
people->age = 30;
people->name = "I am C++";
return 100;
}
int setPeoples(Peoples peoples) {
for (int i = 0; i < peoples.count; i ++) {
logger.writeLog("Call setPeoples from C#: age: %d, name: %s\r\n", peoples.people[i].age, peoples.people[i].name);
}
return 100;
}
int modifyPeoples(Peoples *peoples) {
logger.writeLog("Call modfiyPeople from C#: count: %d\r\n", peoples->count);
for (int i = 0; i < peoples->count; i ++) {
peoples->people[i].age = 30;
peoples->people[i].name = "I am people list from C++";
}
return 100;
}
int setPeopleList(PeopleList peopleList) {
logger.writeLog("Call setPeopleList People1 age: %d, name: %s, People2 age: %d, name: %s\r\n", peopleList.people1.age, peopleList.people1.name, peopleList.people2.age, peopleList.people2.name);
return 100;
}
int modifyPeopleList(PeopleList *peopleList) {
logger.writeLog("Call modifyPeopleList from C#.\r\n");
peopleList->people1.age = 30;
peopleList->people1.name = "I am people1 from C++";
peopleList->people2.age = 30;
peopleList->people2.name = "I am people2 from C++";
return 100;
}
void initCallback(Func_Pointer funcPointer, Func_Pointer funcPointer2) {
callback1 = funcPointer;
callback2 = funcPointer2;
}
void testCallback() {
callback1(1, true, "I am callback1 from C++");
callback2(2, false, "I am callback2 from C++");
}
#ifndef __cplusplus
}
#endif
C# 接口文件:
using System.Runtime.InteropServices;
using System;
using AOT;
[StructLayout(LayoutKind.Sequential)]
public struct People {
public int age;
public IntPtr name;
}
[StructLayout(LayoutKind.Sequential)]
public struct PeopleList {
public People people1;
public People people2;
}
[StructLayout(LayoutKind.Sequential)]
public struct Peoples {
public int count;
public IntPtr peopleListPtr;
}
public delegate void On_C_Plus_Plus_Callback(int a, bool b, string c);
public class NativeBridge {
public const string libName = "c_sharp_to_c_plus";
[DllImport(libName, CharSet = CharSet.Ansi)]
public static extern int startLogService();
[DllImport(libName, CharSet = CharSet.Ansi)]
public static extern int getSumValue(int value1, int value2);
[DllImport(libName, CharSet = CharSet.Ansi)]
public static extern int setPeople(People people);
[DllImport(libName, CharSet = CharSet.Ansi)]
public static extern int modifyPeople(ref People people);
[DllImport(libName, CharSet = CharSet.Ansi)]
public static extern int setPeoples(Peoples peoples);
[DllImport(libName, CharSet = CharSet.Ansi)]
public static extern int getPeoples(ref Peoples peoples);
[DllImport(libName, CharSet = CharSet.Ansi)]
public static extern int setPeopleList(PeopleList peopleList);
[DllImport(libName, CharSet = CharSet.Ansi)]
public static extern int modifyPeopleList(ref PeopleList peopleList);
[DllImport(libName, CharSet = CharSet.Ansi)]
public static extern void testCallback();
[DllImport(libName, CharSet = CharSet.Ansi)]
public static extern void initCallback(On_C_Plus_Plus_Callback callback, On_C_Plus_Plus_Callback callback2);
}
调用示例:
using System.Runtime.InteropServices;
using UnityEngine;
using AOT;
public class HelloUnity : MonoBehaviour {
// Use this for initialization
void Start()
{
People people = new People();
people.age = 50;
people.name = Marshal.StringToHGlobalAnsi("Bobo");
int ret1 = NativeBridge.startLogService();
Debug.LogFormat("startLogService ret1 = {0} ", ret1);
int ret2 = NativeBridge.getSumValue(100, 200);
Debug.LogFormat("startLogService ret2 = {0} ", ret2);
int ret3 = NativeBridge.setPeople(people);
Debug.LogFormat("setPeople ret3 = {0} ", ret3);
int ret4 = NativeBridge.modifyPeople(ref people);
Debug.LogFormat("modifyPeople ret4 = {0}, age = {1} ,name = {2} ", ret4, people.age, Marshal.PtrToStringAnsi(people.name));
People p1 = new People();
p1.age = 50;
p1.name = Marshal.StringToHGlobalAnsi("bobo");
People p2 = new People();
p2.age = 100;
p2.name = Marshal.StringToHGlobalAnsi("bobo2");
PeopleList peopleList = new PeopleList();
peopleList.people1 = p1;
peopleList.people2 = p2;
int ret5 = NativeBridge.setPeopleList(peopleList);
Debug.LogFormat("setPeopleList ret5 = {0} ", ret5);
int ret6 = NativeBridge.modifyPeopleList(ref peopleList);
Debug.LogFormat("setPeopleList ret6 = {0} ", ret6);
NativeBridge.initCallback(On_C_Plus_Plue_Callback_1, On_C_Plus_Plue_Callback_2);
NativeBridge.testCallback();
}
[MonoPInvokeCallback(typeof(On_C_Plus_Plus_Callback))]
public static void On_C_Plus_Plue_Callback_1(int a, bool b, string c) {
Debug.LogFormat("On_C_Plus_Plue_Callback1 a: {0}, b: {1}, c: {2}", a, b, c);
}
[MonoPInvokeCallback(typeof(On_C_Plus_Plus_Callback))]
public static void On_C_Plus_Plue_Callback_2(int a, bool b, string c)
{
Debug.LogFormat("On_C_Plus_Plue_Callback1 a: {0}, b: {1}, c: {2}", a, b, c);
}
}
输出结果:
基础项目链接:
Sample github 链接.
全平台高级进阶项目:
全平台(Android, iOS, Windows, macOS 全平台插件高级进阶项目 github 链接).