天天看点

unity与C++之间的一些交互

C# 传递数据到 C++

步骤:

  1. 先在C++端定义好对应结构 数据基本类型方法都一样 Int Float bool 等

这里介绍两种, 一种是基本数据类型,一种是 结构体类型

首先用visual studio 新建一个DLL项目

unity与C++之间的一些交互
C++端文件配置

新建一个Bridge的类

h文件定义如下

#pragma once
//Bridge.h
#ifdef WIN32
#ifdef  UNITY_CPP_INTEROP_DLL_BRIDGE
#define UNITY_CPP_INTEROP_DLL_BRIDGE    __declspec(dllexport)
#else
#define UNITY_CPP_INTEROP_DLL_BRIDGE    __declspec(dllimport)
#endif
#else
// Linux
#define UNITY_CPP_INTEROP_DLL_BRIDGE
#endif
#include <string>
#include <sstream>
using namespace std;
struct Person
{
public:
    int Age;
    float Height;
    int Scores[4];
    bool Married;
};

extern "C"
{
    UNITY_CPP_INTEROP_DLL_BRIDGE int  IntParameter(int a);
    //传递的结构体
    UNITY_CPP_INTEROP_DLL_BRIDGE void StructParameter(Person* p);
    UNITY_CPP_INTEROP_DLL_BRIDGE void RegisterStructPtr(NativeCallUnity::CallStructPtr ptr);
    UNITY_CPP_INTEROP_DLL_BRIDGE void CallStructStruct();
}
           

CPP文件如下:

#include "Bridge.h"
#include <stdlib.h>

extern "C"
{
    int  IntParameter(int a) {
        a = 101;
        return a;
    }

    void StructParameter(Person* p) {
        p->Age += 10;
        p->Height += 10;
        p->Scores[0] += 10;
        p->Scores[1] += 10;
        p->Married = true;
    }

    void CallStructStruct(){
        Person www = Person();
        NativeCallUnity::transmitStruct(list);
     }
     void RegisterStructPtr(NativeCallUnity::CallStructPtr ptr) {
        NativeCallUnity::SetStructPtrCallBackFuncPtr(ptr);
    }
}
           
C#端配置文件

然后在C#端也需要做一些想对应的配置

  1. 基本类型的配置
//如果只是传递基本数据类型
[DllImport("native", EntryPoint = "IntParameter")]
//这里也可以自定函数名 比如把 IntParameter 改成 TransferInt
private static extern int IntParameter(int a);
//调用的地方需要
int a = 5;
int b = IntParameter(a);
//这样就可以把C#数据传递给C++ 并得到对应的返回值  如果函数名更改了这里就应该调用TransferInt(a);
           
  1. 结构体的配置
public struct Person
{
    public int Age;
    public float Height;
    [MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)]
    public int[] Scores;
    public bool Married;
}

//同样在调用之前先需要声明
[DllImport("native", EntryPoint = "StructParameter")]
private static extern void StructParameter(IntPtr p);
//然后在调用的地方
Person per;
IntPtr p = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(Person)));
StructParameter(p);
Person pOut = (Person)Marshal.PtrToStructure(p, typeof(Person));
Debug.Log(string.Format("StructParameter(): {0}", pOut.Age));
           

上面是关于C# 传递数据给C++的一些配置

C++端传递数据给C#端

首先在C#段需要注册函数到C++端. 然后C++在合适的时候才可以调用C#端的函数 传递 或者得到数据

C#端的文件配置
//必须在脚本文件中包含这个类才可以产生回调
public class MonoPInvokeCallbackAttribute : Attribute
{
    public MonoPInvokeCallbackAttribute() { }
}
//定义好对应的注册方法
[DllImport("native")]
public static extern void RegisterStructPtr(StructDelegate fp);
[MonoPInvokeCallback]
//然后定义好对应的回调方法
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate void StructDelegate(Person per);

//首先在脚本的Start()函数注册对应的回调函数   使用C++端定义好的函数注册
RegisterStructPtr(CallBackStructStructFunction);

[MonoPInvokeCallback]
static void CallBackStructStructFunction(Person p){
     Debug.Log("CallBackStructStructFunction : " + p.Age);
}

//还有一种可以使用void 直接接收,但是需要转换
//使用方法
Person per = IntPtrToStruct<Person>(strPtr);
//转换函数
public static T IntPtrToStruct<T>(IntPtr info)
{
    return (T)Marshal.PtrToStructure(info, typeof(T));
}

           
C++端(完成头文件上面有)
UNITY_CPP_INTEROP_DLL_BRIDGE void RegisterStructPtr(NativeCallUnity::CallStructPtr ptr);
UNITY_CPP_INTEROP_DLL_BRIDGE void CallStructStruct();

           

NativeCallUnity 是关于C++中调用C#函数的

文件如下

NativeCallUnity.h

#include <iostream>
#include <string>
using namespace std;
class NativeCallUnity
{
public:
    typedef void(*CallStructPtr)(Person*);
    static CallStructPtr StructPtr;
    static void SetStructPtrCallBackFuncPtr(CallStructPtr ptr);
    static void transmitStruct(const Person list);
};
           

NativeCallUnity.cpp

#include "NativeCallUnity.h"
//定义接收的函数指针
NativeCallUnity::CallStructPtr NativeCallUnity::StructPtr;
//注册函数
void NativeCallUnity::SetStructPtrCallBackFuncPtr(CallStructPtr ptr){
    StructPtr = ptr;
 }
//调用函数
void NativeCallUnity::transmitStruct(const Person list)
{
     logI("123","%s",__func__);
    if (FuncPtr != nullptr)
    {
        logI("123","%s   called",__func__);
        StructPtr((VrObjectList *)&list);
    }
}
           

上面是C++文件相关的配置

C++调用C#函数的地方

void CallStructStruct(){
    Person www = Person();
    //调用保存的函数
    NativeCallUnity::transmitStruct(list);
 }
//注册函数到NativeCallUnity中保存
 void RegisterStructPtr(NativeCallUnity::CallStructPtr ptr) {
    NativeCallUnity::SetStructPtrCallBackFuncPtr(ptr);
}
           

这样就实现了 两者间的互相调用

(******************出差期间偷师于 斑马智行同事************************)

继续阅读