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

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

上記のコードを使用してクラス ライブラリ プロジェクトに貼り付け、3.5 以下の .NET でコンパイルします。

生成された 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: (「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
名前のない
火星
地球は私の故郷です。その直径は約12742kmです。私たちの隣人は火星です

それがあなたの何人かを助けることを願っています。

編集 1: ちなみに、lua からのメソッド呼び出しは次のようになります。

PlanetObject1:testMethod()
PlanetObject2:testMethod()

編集 2: さまざまな dll を別の方法で処理する必要があることがわかりました。1 つは「インポート」機能が必要で、もう 1 つは「load_assembly」機能が必要でした。多分それを覚えておいてください!

于 2015-04-09T08:01:26.450 に答える
0

この数日間、LuaInterface のまさにこの機能を必要とするプロジェクトに取り組んでいたときに、完璧なソリューションであることが判明した Lua コードの一部に出くわしました (参考文献 1 を参照)。この解決策を探しているときに、この質問に気づき、2 セントを投じようと考えました。

このソリューションを適用するには、LuaInterface Lua オブジェクトを初期化しながら CLRPackage コードを実行するだけです。ただし、require ステートメントも同様に機能します。

リファレンス 1 で提供されているコードでは、C# の using ステートメントと同様に、import ステートメントを使用できます。アセンブリがインポートされると、そのメンバーはグローバル名前空間でアクセスできます。import ステートメントを使用すると、load_assembly または import_type を使用する必要がなくなります (別のアセンブリから同じ名前のメンバーを使用する必要がある場合を除きます。このシナリオでは、NewTypeName = Assembly.OldTypeName を使用して C# と同様に import_type を使用します)。

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 に答える
0

だから私も同じように多くの時間を費やしました。本当に私を夢中にさせたのは、列挙型を機能させようとしたことでした。最終的に、非常に単純化されたコンソール アプリケーション (皮肉なことに「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 に答える