简体   繁体   English

如何在Unity 3D中包含SWIG包装的C ++?

[英]How can I include SWIG-wrapped C++ in Unity 3D?

My goal is to get a toy C++ library wrapped using SWIG, and accessible to C# / Mono scripts in Unity. 我的目标是使用SWIG封装玩具C ++库,并且可以访问Unity中的C#/ Mono脚本。 (In other words, have the library functionality working in a Windows build of the game. I'll tackle Android next :) (换句话说,让图书馆功能在游戏的Windows版本中运行。我将在下一步处理Android :)

I have been following a combination of Build a C# module (SWIG tutorial), Unity and DLLs (Eric Eastwood) and Getting started with SWiG for Visual Studio projects (Technical Recipes). 我一直在关注Build a C#模块 (SWIG教程), Unity和DLL (Eric Eastwood)以及SWiG for Visual Studio项目入门 (技术食谱)的组合。 I have generated two DLLs in Visual Studio 2013 and added them to the Unity project. 我在Visual Studio 2013中生成了两个DLL,并将它们添加到Unity项目中。 But accessing the toy method at runtime is failing. 但是在运行时访问玩具方法失败了。


Steps I followed (including common fixes for the error I am receiving): 我遵循的步骤(包括我收到的错误的常见修复):

Create C++ project / custom build 创建C ++项目/自定义构建

  • Create a C++ Win32 Console Application project in Visual Studio 在Visual Studio中创建C ++ Win32控制台应用程序项目
    • (because MonoDevelop on Windows cannot compile C++) (因为Windows上的MonoDevelop无法编译C ++)
  • Add example code to the project 将示例代码添加到项目中
  • Create example.i (interface file for SWIG) 创建example.i(SWIG的接口文件)
  • Create an Custom Build Tool for the interface file 为接口文件创建自定义构建工具
  • Execute the Custom Build Tool (generates wrapper code for C++ and C#) 执行自定义构建工具(为C ++和C#生成包装器代码)
  • Add C++ wrapper code to project (will be used later to generate C++ DLL) 将C ++包装器代码添加到项目中(稍后将用于生成C ++ DLL)

Create C# project 创建C#项目

  • Create a C# Class Library project in Visual Studio 在Visual Studio中创建C#类库项目
  • Change Target Framework version 3.5 更改目标框架版本3.5
  • Add C# wrapper code files to project root 将C#包装器代码文件添加到项目根目录
  • Add the following library references and namespace to the C# wrapper files: 将以下库引用和命名空间添加到C#包装器文件中:
using System;
using System.Runtime.InteropServices;

namespace CSharpExampleLib {
...
}

Build two Release DLLs 构建两个Release DLL

  • Set the build settings to Release / x86 for both projects 将构建设置设置为两个项目的Release / x86
  • Set the target for the C# build to the target of the C++ build 将C#构建的目标设置为C ++构建的目标
  • Build the solution (generates two DLLs, one per project) 构建解决方案(生成两个DLL,每个项目一个)
  • Confirm with Dependency Walker that the DLLs do not see each other as missing (reference) 使用Dependency Walker确认DLL没有看到彼此丢失(参考)
  • Used CorFlags to force the C# DLL to be 32-bit (reference) (this does not work / does not apply to C++ DLL) 使用CorFlags强制C#DLL为32位(引用) (这不起作用/不适用于C ++ DLL)

Add DLLs to Unity project 将DLL添加到Unity项目

  • Create a new project in Unity 4 (Pro) with a simple Mono script 使用简单的Mono脚本在Unity 4(Pro)中创建一个新项目
  • Close Unity project 关闭Unity项目
  • Copy the DLLs into Assets/Plugins folder 将DLL复制到Assets / Plugins文件夹中
  • Reopen the Unity project (DLLs recognised) 重新打开Unity项目(已识别的DLL)
  • Right-click on Assets in the Project Hierarchy, select "Synch with MonoDevelop..." (opens simple script in MonoDevelop, ensures DLLs are accessible) 右键单击Project Hierarchy中的Assets,选择“与MonoDevelop同步...”(在MonoDevelop中打开简单脚本,确保可以访问DLL)
  • Added library references to the simple script: 添加了对简单脚本的库引用:
using System.Runtime.InteropServices;
using System.IO;

Invoke method from DLL 从DLL调用方法

Finally, I added a logging call from the simple script to the C# DLL (Intellisense confirms that the DLL and method are accessible): 最后,我添加了从简单脚本到C#DLL的日志记录调用(Intellisense确认可以访问DLL和方法):

Debug.Log(CSharpExampleLib.example.fact(3));
// should log the result of 3 factorial

Runtime error 运行时错误

However, when I start the game from the Unity editor, I get the following error: 但是,当我从Unity编辑器启动游戏时,我收到以下错误:

DllNotFoundException: example
CSharpExampleLib.examplePINVOKE+SWIGExceptionHelper..cctor ()
Rethrow as TypeInitializationException: An exception was thrown by the type initializer for SWIGExceptionHelper
CSharpExampleLib.examplePINVOKE..cctor ()
Rethrow as TypeInitializationException: An exception was thrown by the type initializer for CSharpExampleLib.examplePINVOKE
CSharpExampleLib.example.fact (Int32 n)
SimpleController.Start () (at Assets/scripts/SimpleController.cs:10)

I made several attempts to correct common causes for this error (build as Release, build as 32-bit, check Dependency Walker, etc) to no avail. 我做了几次尝试来纠正这个错误的常见原因(构建为Release,构建为32位,检查Dependency Walker等)无济于事。 Is there something SWIG- or Unity-specific I am missing? 是否有某些SWIG或Unity特定的东西我缺少? Any other checks I can perform on my DLLs? 我可以在我的DLL上执行的任何其他检查?

After discussion on the SWIG user mailing list and some careful review, I discovered I was missing two configuration steps: 在对SWIG用户邮件列表进行讨论并仔细审查后,我发现我缺少两个配置步骤:

  1. The C++ DLL must have the same name as the module name specified in the SWIG interface file (so for my toy example using interface file example.i, it is best to name the C++ project "example" and it will generate example.dll) C ++ DLL必须与SWIG接口文件中指定的模块名称相同(因此对于使用接口文件example.i的玩具示例,最好将C ++项目命名为“example”,它将生成example.dll)

  2. In the backwards and forwards of resolving other issues, I lost the reference to the autogenerated C++ wrapper (example_wrap.cxx) and needed to re-add it to the C++ project. 在解决其他问题的后退和前进中,我丢失了对自动生成的C ++包装器(example_wrap.cxx)的引用,需要将其重新添加到C ++项目中。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM