2012-11-19 2 views
2

В моем пространстве имен LuaTest у меня есть класс под названием «Планета». # Код C читается как это:Сопоставление классов C# с функциями Lua через dll

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

У меня были некоторые реальные проблемы, когда я использовал LuaInterface. Вы можете захотеть взглянуть на C# Compiling на лету. –

+0

@Ruirize Спасибо за комментарий. Неужели эти «реальные проблемы» заставили вас отказаться от этого подхода в конце? Я посмотрю на C# Compiling «на лету». Надеюсь, это не сложно. – proudnoldo

+0

В принципе, я не мог разоблачить свои классы C# для Lua без длительного обхода, что сделало полученный код Lua очень уродливым. (С тех пор я проиграл проект, это было давно). C# Compiling - это очень просто, и вы можете контролировать то, что открывается, используя модификаторы доступа. –

ответ

0

Так что я провел много времени аналогичным образом. То, что на самом деле заставило меня запугивать, пыталось заставить Enums работать. В конце концов я бросил свой проект на очень упрощенное консольное приложение, очень похожее (по иронии судьбы, также называемое «LuaTest»).

Редактировать: Я отметил, что первоначальная «luanet.load_assembly (« LuaTest »)« кажется излишней. Работает с ним, или на удивление без него.

Другой Edit: Как и в моем плохо отредактированный комментарий ниже, когда я снял:

print(luanet.LuaTest.Pointless) 

Все перестали работать (LuaTest.Pointless стал ноль). Но добавление luanet.load_assembly («LuaTest») заставляет его работать. Возможно, в печати есть какая-то нечетная неявная нагрузка или просто выражающая их тип. Очень странно (тм).

В любом случае, это работает для меня (примечание: после много экспериментов). Я не знаю, почему твоя не удается, я не замечаю никакой реальной разницы, но вот весь мой код в случае, если кто-то может заметить критическую разницу:

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' 
+0

Любопытный. Я работаю с этим сегодня, возиться с подклассами объектов CLR. Вызов элементов в подклассе (PointlessTwo) работал до тех пор, пока я не удалил строку: 'print (luanet.LuaTest.Pointless)' Когда я удалил эту строку, она перестала работать. Но добавление luanet.load_assembly («LuaTest») заставило его снова работать! Есть ли какая-то неявная нагрузка с печатью (luanet.LuaTest.Pointless)? Интересно. –

0

Проведя последние несколько дней, работая над проектом, который требовал этой точной функциональности от LuaInterface, я наткнулся на кусок кода Lua, который оказался идеальным решением (см. Ссылку 1). Во время поиска этого решения я заметил этот вопрос и решил, что я бы сбросил свои два цента.

Чтобы применить это решение, я просто запускаю код CLRPackage при инициализации моего объекта LuaInterface Lua. Однако требование require работает так же хорошо.

Код, приведенный в ссылке 1, позволяет использовать операторы импорта, аналогичные операциям с C#. Когда сборка импортируется, ее члены доступны в глобальном пространстве имен. Оператор 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/

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. Вставьте его, например, в папку «клиффы» или другой известный путь системы 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: (Вариант 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
Constructor 2
безымянный
Марс
Планета Земля моя родная планета. Его диаметр составляет около 12742 км. Наш сосед Марс

Я надеюсь, что это поможет некоторым из вас.

Edit 1: , кстати, способ вызова из Lua выглядит следующим образом:

PlanetObject1:testMethod() 
PlanetObject2:testMethod() 

Edit 2: Я нашел ведьма различных DLL, нужно обращаться по-разному. Одной из них нужна функция «импорт», а другая нужна «load_assembly» -функция. Держите это, возможно, в виду!

Смежные вопросы