在我的“LuaTest”命名空间中,我有一个名为“Planet”的类。 C#代码如下所示:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using LuaInterface;
namespace LuaTest
{
public class Planet
{
public Planet(string name)
{
this.Name = name;
}
public Planet() : this("NoName") { }
public string Name
{
get;
private set;
}
public void printName()
{
Console.WriteLine("This planet's name is {0}", Name);
}
}
}
然后我构建了LuaTest.dll并将此文件复制到保存我的Lua脚本的同一文件夹中。在Lua脚本中,我写道:
--define Path for required dlls
package.cpath = package.cpath .. ";" .. "/?.dll"
package.path = package.path .. ";" .. "/?.dll/"
require 'luanet'
luanet.load_assembly("LuaTest")
local Planet = luanet.import_type("LuaTest.Planet")
local planet = Planet("Earth")
planet.printName()
但是,这段代码不起作用。 Lua解释器抛出了这个错误:
lua: dllTest.lua:7: attempt to call local 'Planet' (a nil value)
我怀疑我的LuaTest程序集根本没有加载。谁能指出我做错了什么?我非常感激,因为我已经被这个问题困扰了好几天。
另外,添加我的LuaInterface.dll是.NET4.0环境中的重建版本可能会有所帮助。
答案 0 :(得分:0)
所以我花了很多时间。真正让我疯狂的是试图让Enums工作。最终我放弃了我的项目,用于非常简化的控制台应用程序,非常相似(具有讽刺意味的是也称为“LuaTest”)。
编辑:我注意到最初的“luanet.load_assembly(”LuaTest“)”似乎是多余的。与它一起使用,或者没有它就会令人惊讶。
另一个编辑:正如我在下面编辑得很糟糕的评论,当我删除时:
print(luanet.LuaTest.Pointless)
一切都停止了工作(LuaTest.Pointless变成了零)。但是添加luanet.load_assembly(“LuaTest”)然后使它工作。可能是在打印中存在某种奇怪的隐式加载或仅仅表达它们的类型。非常奇怪(tm)。
无论如何,它似乎对我有用(注意:经过大量实验)。我不知道为什么你的失败,我没有注意到任何真正的区别,但这是我的所有代码,万一其他人可以发现关键的区别:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using LuaInterface;
namespace LuaTest
{
public class Program
{
static void Main(string[] args)
{
Lua lua = new Lua();
lua.DoFile("test.lua");
}
public int some_member = 3;
}
public class Pointless
{
public enum AnEnum
{
One,
Two,
Three
};
public static string aStaticInt = "This is static.";
public double i;
public string n = "Nice";
public AnEnum oneEnumVal = AnEnum.One;
private AnEnum twoEnumVal = AnEnum.Two;
private string very;
public Pointless(string HowPointLess)
{
i = 3.13;
very = HowPointLess;
}
public class MoreInnerClass
{
public string message = "More, please!";
}
public void Compare(AnEnum inputEnum)
{
if (inputEnum == AnEnum.Three)
Console.WriteLine("Match.");
else
Console.WriteLine("Fail match.");
}
}
}
和test.lua:
luanet.load_assembly("LuaTest")
--Pointless is a class in LuaTest assembly
local Pointless = luanet.import_type("LuaTest.Pointless")
print(Pointless)
--Gives 'ProxyType(LuaTest.Pointless): 46104728
print(Pointless.aStaticInt)
--'This is static.'
--Fails if not static, as we expect
--Instantiate a 'Pointless'.
local p = Pointless("Very")
print(p)
--Gives 'LuaTest.Pointless: 12289376'
--Now we can get at the items inside the Pointless
--class (well, this instance, anyway).
local e = p.AnEnum;
print(e)
--ProxyType(LuaTest.Pointless+AnEnum): 23452342
--I guess the + must designate that it is a type?
print(p.i)
--3.14
print(p.oneEnumVal)
--Gives 'One: 0'
print(p.twoEnumVal)
--Gives 'twoEnumVal'... private
--behaves very differently.
print(e.Two:ToString())
--Gives 'Two'
local more = p.MoreInnerClass()
print(more.message)
--'More, Please!'
--create an enum value here in the script,
--pass it back for a comparison to
--the enum.
local anotherEnumVal = p.AnEnum.Three
p:Compare(anotherEnumVal)
--outputs 'Match'
答案 1 :(得分:0)
过去几天在LuaInterface上开发了一个需要这个功能的项目,我偶然发现了一段Lua代码,结果证明这是一个完美的解决方案(参见参考文献1)。在寻找这个解决方案的过程中,我注意到了这个问题,并认为我会把我的两分钱放进去。
要应用此解决方案,我只是在初始化LuaInterface Lua对象时运行CLRPackage代码。但是,require语句也可以正常工作。
参考文献1中提供的代码允许使用import语句,类似于C#using语句。导入程序集后,可以在全局名称空间中访问其成员。 import语句不需要使用load_assembly或import_type(在需要使用来自不同程序集的同名成员的情况下除外。在这种情况下,import_type将类似于使用NewTypeName = Assembly.OldTypeName的C#。) / p>
import "LuaTest"
planet = Planet("Earth")
planet:printName()
此软件包也适用于枚举!
有关使用此包装的更多信息,请参阅参考文献2。
希望这有帮助!
参考文献1:https://github.com/stevedonovan/MonoLuaInterface/blob/master/bin/lua/CLRPackage.lua 参考文献2:http://penlight.luaforge.net/project-pages/penlight/packages/LuaInterface/
答案 2 :(得分:0)
我花了一些时间将C#dll绑定到lua。你的帖子很有帮助,但缺少了一些东西。 以下解决方案应该有效:
(确保将编译器更改为.NET Framework 3.5或更低版本!)
<强> Planet.dll:强>
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Planets
{
public class Planet
{
private string name;
public string Name
{
get { return name; }
set { this.name = value; }
}
private float diameter;
public float Diameter
{
get { return diameter; }
set { this.diameter = value; }
}
private int cntContinents;
public int CntContinents
{
get { return cntContinents; }
set { this.cntContinents = value; }
}
public Planet()
{
Console.WriteLine("Constructor 1");
this.name = "nameless";
this.diameter = 0;
this.cntContinents = 0;
}
public Planet(string n, float d, int k)
{
Console.WriteLine("Constructor 2");
this.name = n;
this.diameter = d;
this.cntContinents = k;
}
public void testMethod()
{
Console.WriteLine("This is a Test!");
}
}
}
使用上面的代码,将其粘贴到您的类库项目中,并使用.NET小于或等于3.5进行编译。
生成的DLL的位置需要由lua环境知道。将其粘贴在“clibs”文件夹或其他众所周知的lua系统路径上。然后尝试使用以下lua示例。它应该工作。
Test1.lua:(来自CLRPackage的“导入”选项1)
require "luanet"
require "CLRPackage"
import "Planet"
local PlanetClass = luanet.import_type("Planets.Planet")
print(PlanetClass)
local PlanetObject1 = PlanetClass()
print(PlanetObject1)
local PlanetObject2 = PlanetClass("Earth",6371.00*2,7)
print(PlanetObject1.Name)
PlanetObject1.Name = 'Mars'
print(PlanetObject1.Name)
print( "Planet " ..
PlanetObject2.Name ..
" is my home planet. Its diameter is round about " ..
PlanetObject2.Diameter .. "km." ..
" Our neighour is " ..
PlanetObject1.Name)
Test2.lua:(选项2带有“load_assembly”)
require "luanet"
require "CLRPackage"
luanet.load_assembly("Planet")
local PlanetClass = luanet.import_type("Planets.Planet")
print(PlanetClass)
local PlanetObject1 = PlanetClass()
print(PlanetObject1)
local PlanetObject2 = PlanetClass("Earth",6371.00*2,7)
print(PlanetObject1.Name)
PlanetObject1.Name = 'Mars'
print(PlanetObject1.Name)
print( "Planet " ..
PlanetObject2.Name ..
" is my home planet. Its diameter is round about " ..
PlanetObject2.Diameter .. "km." ..
" Our neighour is " ..
PlanetObject1.Name)
在这两种情况下,控制台输出将如下所示:
ProxyType(Planets.Planet):18643596
构造函数1
Planets.Planet:33574638
构造函数2
无名
火星
行星地球是我的家乡。它的直径约为12742km。我们的邻居是火星
我希望它可以帮助你们中的一些人。
编辑1: 顺便说一下,来自lua的方法调用如下所示:
PlanetObject1:testMethod()
PlanetObject2:testMethod()
编辑2: 我发现不同的dll需要以不同的方式处理。一个需要“导入”功能,另一个需要“load_assembly”功能。请记住这一点!