大家好我在unity3d pro上遇到一些问题,也许有人使用DLL本机插件可以解释我做错了什么。
首先,我将解释我的目标是什么。我有一个来自西门子PLCSim软件的COM对象,我已经得到了与Visual Studio一起工作的功能。以下是测试代码。
namespace WindowsFormsApplication1
{
public partial class Form1 : Form
{
public S7PROSIMLib.S7ProSim PLCSimConn = new S7PROSIMLib.S7ProSim();
public Form1()
{
InitializeComponent();
}
private void button_Connect_Click(object sender, EventArgs e)
{
PLCSimConn.Connect();
label_CPUState.Text = PLCSimConn.GetState();
label_ScanMode.Text = PLCSimConn.GetScanMode().ToString();
}
}
}
我创建了一个unity3d项目来测试它。我将dll导入到我的资产中,并且我能够从我的c#脚本中调用S7PROSIMLib的方法和实例。 COM Api,https://cache.industry.siemens.com/dl/files/855/1139855/att_29424/v1/S7WSPSCB.pdf
using UnityEngine;
using System.Collections;
using System.Runtime.InteropServices;
using S7PROSIMLib;
public class TestNative : MonoBehaviour {
public S7ProSimClass ps;
// Use this for initialization
void Start () {
ps = new S7ProSimClass ();
ps.Connect ();
Debug.Log (ps.GetState());
}
}
现在在运行时我得到以下内容:
收到COMException
System.Runtime.InteropServices.Marshal.ThrowExceptionForHR (Int32 errorCode) (at /Users/builduser/buildslave/mono-runtime-and-classlibs/build/mcs/class/corlib/System.Runtime.InteropServices/Marshal.cs:1031)
System.__ComObject.Initialize (System.Type t) (at /Users/builduser/buildslave/mono-runtime-and-classlibs/build/mcs/class/corlib/System/__ComObject.cs:103)
(wrapper remoting-invoke-with-check) System.__ComObject:Initialize (System.Type)
Mono.Interop.ComInteropProxy.CreateProxy (System.Type t) (at /Users/builduser/buildslave/mono-runtime-and-classlibs/build/mcs/class/corlib/Mono.Interop/ComInteropProxy.cs:108)
System.Runtime.Remoting.RemotingServices.CreateClientProxyForComInterop (System.Type type) (at /Users/builduser/buildslave/mono-runtime-and-classlibs/build/mcs/class/corlib/System.Runtime.Remoting/RemotingServices.cs:588)
System.Runtime.Remoting.Activation.ActivationServices.CreateProxyForType (System.Type type) (at /Users/builduser/buildslave/mono-runtime-and-classlibs/build/mcs/class/corlib/System.Runtime.Remoting.Activation/ActivationServices.cs:234)
TestNative.Start () (at Assets/Scripts/TestNative.cs:13)
我已经看过了不会调用第三方DLL的unity3d插件教程https://www.youtube.com/watch?v=DfRYLwG1Bug。
我已阅读以下内容:https://msdn.microsoft.com/en-us/library/ms973872.aspx,其中包含有关非托管和托管DLL的大量有用信息。
基于以上链接中的以下代码段:
调用COM API 有两种方法可以从托管代码调用COM组件:通过COM interop(在所有托管语言中都可用)或通过C ++ interop(在C ++中可用)。 为了调用与OLE Automation兼容的COM组件,建议使用COM互操作。 CLR将负责COM组件激活和参数编组。
为了基于接口定义语言(IDL)调用COM组件,建议使用C ++互操作。 C ++层可以非常精简,其余的托管代码可以用任何托管语言编写。 COM interop依赖于类型库中的信息来进行正确的互操作调用,但类型库通常不包含IDL文件中存在的所有信息。使用C ++ interop允许直接访问这些COM API来解决这个问题。
我相信我已经在上面的Unity c#脚本中显示了COM互操作。这没有用。我的另一个选择是通过C ++互操作,但我还没有在网上找到任何例子。大多数示例都很简单,无需调用COM对象或任何其他第三方DLL。如果有人能以正确的方式指导我,我将不胜感激。基本上,它归结为什么是最好的方法,最少的重写方法?谢谢!
Edit1:我在youtube上看过这个视频来自有人让它上班,但我还没有得到他的回复。至少我知道它应该适用于unity3d。 https://www.youtube.com/watch?v=EGFMjUJN7ZU
Edit2:Unity3d - Failed to load 'Assets/Plugins/QCARWrapper.dll'将尝试使用32位编辑器,如本帖所示。
答案 0 :(得分:0)
对于任何可能需要帮助的人。西门子PLCSim COM类型库仅适用于32位Unity编辑器。
经过大量的试验和错误,解决方案实际上非常简单,还有更多的阅读通过论坛,什么不是。我使用tlbimp.exe生成一个类型库DLL,然后我将它放入assets / plugins文件夹中,同时注意unity3d编辑器属性,将新DLL视为托管代码。请注意,此特定DLL在64位Unity编辑器上不起作用,并且它抛出了COMException。但是,新类型库DLL在32位Unity编辑器中工作正常,我想在DLL中的某个地方有一条指令只能在32位工作。
我在这里记录了存储库中的所有内容https://github.com/fredz0003/myS7ProSimLib我还放置了托管DLL以供将来使用,因此您不会遇到麻烦。
以下是示例代码:
using UnityEngine; using myS7ProSimLib;
public class TestNative : MonoBehaviour {
/*
* Used tlbimp.exe to generate library DLL
* place new generated DLL on assets/plugins
* also note that the DLL is treated as managed code
*/
public S7ProSimClass ps;
public bool input_0_0;
void Start () {
ps = new S7ProSimClass();
ps.Connect();
print("State " + ps.GetState());
ps.SetScanMode(ScanModeConstants.ContinuousScan);
// Here we pass the ref as an obj, since WriteInputPoint method
// can take bit, word, dwords, as addresses ref obj can take the
// for of bool, int, float, etc.
object refInput0_0 = input_0_0;
ps.WriteInputPoint(0, 0, ref refInput0_0); } }