您的位置:首页 > 移动开发 > Unity3D

unity3D C#调用C++代码(通过DLL链接库方式)

2018-01-26 13:48 1436 查看
前言】:最近自己捣鼓数据手套,想用unity3D集成数据手套CyberGlove,开发一个数据手套可以控制的虚拟手交互场景。还没开始就遇到一个麻烦的问题,unity3D支持C#脚本,而数据手套CyberGlove只提供了静态链接库.lib和头文件.h作为开发的SDK。于是乎如何在unity3D中获取数据手套的各指关节角度成为一个麻烦事,经过多方查询资料,初步形成了以下方案。
方案】:分析unity3D中需要用到数据手套CyberGlove的那些API,将其提取出来进行封装,即在VS上建立DLL工程,然后定义新的函数,这些函数调用数据手套CyberGlove的API,接着将工程编译生成DLL。然后在unity3D通过调用该DLL中的函数,间接调用数据手套的原始API。借鉴网上C#调用C++ DLL库的方法,整个实现过程记录如下。

步骤

(1)提取unity3D需要调用数据手套API,如下:

#include <vhandtk/vhtBase.h>
1、获得手套的连接
vhtIOConn *gloveConn = vhtIOConn::getDefault(vhtIOConn::glove);
2、创建手套
vhtCyberGlove *glove = new vhtCyberGlove(gloveConn);
3、手套刷新
glove->update();
4、获取角度
double distalAngle = glove->getAngle(GHM::index, GHM::distal);
for( int finger = 0; finger < GHM::nbrFingers; finger++ )
{
for( int joint = 0; joint < GHM::nbrJoints; joint++ )
{
glove->getData( (GHM::Fingers)finger,(GHM::Joints)joint)
}
}

//设置震动幅度
double vibrations[] = {.5, .5, .5, .5, .5, .5};
myTouchGlove->setVibrationAmplitude( vibrations );
(2)利用VS制作DLL库,基本代码模板如下:

头文件 XXX.h:
#if defined (EXPORTBUILD)
# define _DLLExport __declspec (dllexport)
# else
# define _DLLExport __declspec (dllimport)
#endif

extern "C"  int _DLLExport 函数名(参数列表);
源文件 XXX.cpp
#define  EXPORTBUILD
#include "XXX.h"
int _DLLExport 函数名(参数列表)
{
实现
}
需要注意的是,编译之前还需要进行一项设置,项目属性->配置属性->常规->项目默认值->公共语言运行时支持,选择“公共语言运行时支持(/clr)”,然后编译生成DLL文件。

(3)unity3D中调用DLL函数,a)将上述DLL文件拷贝到unity3D工程的assert/Plugins目录下,在C#文件最上方添加命名空间,using System.Runtime.InteropServices; 然后在需要调用DLL中的函数的地方(C#函数外)添加函数声明,格式如下:

[DllImport ("DLL文件.dll", CallingConvention=CallingConvention.Cdecl), EntryPoint="新函数名")]
[private] static extern int 函数名(参数列表);
其中,CallingConvention为入口点调用约定,EntryPoint为入口点名称。其余还有很多参数可以根据需要设置,

[AttributeUsage(AttributeTargets.Method)]
  public class DllImportAttribute: System.Attribute
  {
   public DllImportAttribute(string dllName) {…} //定位参数为dllName
   public CallingConvention CallingConvention; //入口点调用约定
   public CharSet CharSet; //入口点采用的字符接
   public string EntryPoint; //入口点名称
   public bool ExactSpelling; //是否必须与指示的入口点拼写完全一致,默认false
   public bool PreserveSig; //方法的签名是被保留还是被转换
   public bool SetLastError; //FindLastError方法的返回值保存在这里
   public string Value { get {…} }
  }
接下来就可以直接调用DLL中的函数了。最后需要补充一点,上述调用方式属于非托管调用。此外,如果unity3D发布成了exe,在其所在目录中,建立Plugins文件夹,并将DLL拷贝到其中,程序也可以运行。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: