2

在我的“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 环境中的重建版本可能会有所帮助。

4

3 回答 3

0

所以我同样花了很多时间。真正让我发疯的是试图让 Enums 工作。最终,我放弃了我的项目,转而使用一个非常简单的控制台应用程序,非常相似(具有讽刺意味的是,它也被命名为“LuaTest”)。

编辑:我注意到最初的“luanet.load_assembly("LuaTest")”似乎是多余的。使用它,或者令人惊讶地没有它。

另一个编辑:正如我在下面编辑错误的评论中,当我删除时:

print(luanet.LuaTest.Pointless)

这一切都停止了工作(LuaTest.Pointless 变为 nil)。但是添加 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'
于 2013-02-01T02:51:00.360 回答
0

我花了一些时间将 C# dll 绑定到 lua。您的帖子很有帮助,但缺少一些东西。以下解决方案应该有效

(确保将编译器更改为 .NET Framework 3.5 或更低版本!)

行星.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!");
        }
    }
}

使用上面的代码,将其粘贴到您的类库项目中,并使用小于或等于 3.5 的 .NET 进行编译。

生成的 DLL 的位置需要 lua 环境知道。将其粘贴到例如“clibs”文件夹或另一个众所周知的 lua 系统路径中。然后尝试使用下面的 lua 示例。它应该工作。

Test1.lua:(选项 1,从 CLRPackage 中“导入”)

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:(带有“load_assembly”的选项2)

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
无名
火星
行星地球是我的家乡星球。它的直径约为12742公里。我们的邻居是火星

我希望它对你们中的一些人有所帮助。

编辑 1: 顺便说一下,来自 lua 的方法调用如下所示:

PlanetObject1:testMethod()
PlanetObject2:testMethod()

编辑 2: 我发现不同的 dll 需要以不同的方式处理。一个需要“import”功能,另一个需要“load_assembly”功能。请记住这一点!

于 2015-04-09T08:01:26.450 回答
0

在过去的几天里,我在一个需要 LuaInterface 的确切功能的项目上工作,偶然发现了一段 Lua 代码,结果证明它是完美的解决方案(参见参考资料 1)。在寻找这个解决方案时,我注意到了这个问题,并认为我会投入两分钱。

要应用此解决方案,我只需在初始化 LuaInterface Lua 对象时运行 CLRPackage 代码。但是,require 语句也同样有效。

参考 1 中提供的代码允许使用 import 语句,类似于 C# using 语句。导入程序集后,可在全局命名空间中访问其成员。import 语句消除了使用 load_assembly 或 import_type 的需要(除了需要使用来自不同程序集的同名成员的情况。在这种情况下,import_type 的使用类似于 C# 使用 NewTypeName = Assembly.OldTypeName)。

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/

于 2013-03-26T19:09:09.937 回答