Commit b969a882 authored by Megax's avatar Megax
Browse files

* Project fajlok at lettek alakitva. Igy most mindegyik normalisan hasznalhato...

* Project fajlok at lettek alakitva. Igy most mindegyik normalisan hasznalhato forditasnal. Nincsenek hibak. KopiLua-ba kerult egy fix. Nem ertem mitol jott elo az a hiba ami elojott de most van a kodban (vagy is volt mert fixaltam).
parent d7bb0c93
/*
* This file is part of LuaInterface.
*
* Copyright (C) 2003-2005 Fabio Mascarenhas de Queiroz.
* Copyright (C) 2012 Megax <http://megax.yeahunter.hu/>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
using System;
namespace LuaInterface
{
/// <summary>
/// Marks a method for global usage in Lua scripts
/// </summary>
/// <see cref="LuaRegistrationHelper.TaggedInstanceMethods"/>
/// <see cref="LuaRegistrationHelper.TaggedStaticMethods"/>
[AttributeUsage(AttributeTargets.Method)]
public sealed class LuaGlobalAttribute : Attribute
{
/// <summary>
/// An alternative name to use for calling the function in Lua - leave empty for CLR name
/// </summary>
public string Name { get; set; }
/// <summary>
/// A description of the function
/// </summary>
public string Description { get; set; }
}
/*
* This file is part of LuaInterface.
*
* Copyright (C) 2003-2005 Fabio Mascarenhas de Queiroz.
* Copyright (C) 2012 Megax <http://megax.yeahunter.hu/>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
using System;
namespace LuaInterface
{
/// <summary>
/// Marks a method for global usage in Lua scripts
/// </summary>
/// <see cref="LuaRegistrationHelper.TaggedInstanceMethods"/>
/// <see cref="LuaRegistrationHelper.TaggedStaticMethods"/>
[AttributeUsage(AttributeTargets.Method)]
public sealed class LuaGlobalAttribute : Attribute
{
/// <summary>
/// An alternative name to use for calling the function in Lua - leave empty for CLR name
/// </summary>
public string Name { get; set; }
/// <summary>
/// A description of the function
/// </summary>
public string Description { get; set; }
}
}
\ No newline at end of file
/*
* This file is part of LuaInterface.
*
* Copyright (C) 2003-2005 Fabio Mascarenhas de Queiroz.
* Copyright (C) 2012 Megax <http://megax.yeahunter.hu/>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
using System;
namespace LuaInterface
{
/// <summary>
/// Marks a method, field or property to be hidden from Lua auto-completion
/// </summary>
[AttributeUsage(AttributeTargets.Method | AttributeTargets.Field | AttributeTargets.Property)]
public sealed class LuaHideAttribute : Attribute
{
}
/*
* This file is part of LuaInterface.
*
* Copyright (C) 2003-2005 Fabio Mascarenhas de Queiroz.
* Copyright (C) 2012 Megax <http://megax.yeahunter.hu/>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
using System;
namespace LuaInterface
{
/// <summary>
/// Marks a method, field or property to be hidden from Lua auto-completion
/// </summary>
[AttributeUsage(AttributeTargets.Method | AttributeTargets.Field | AttributeTargets.Property)]
public sealed class LuaHideAttribute : Attribute
{
}
}
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="4.0">
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProductVersion>9.0.21022</ProductVersion>
<SchemaVersion>2.0</SchemaVersion>
<ProjectGuid>{F55CABBB-4108-4A39-94E1-581FD46DC021}</ProjectGuid>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>LuaInterface</RootNamespace>
<AssemblyName>LuaInterface</AssemblyName>
<OldToolsVersion>2.0</OldToolsVersion>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
<Reference Include="System.Data" />
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="CheckType.cs" />
<Compile Include="Lua.cs" />
<Compile Include="Metatables.cs" />
<Compile Include="ObjectTranslator.cs" />
<Compile Include="ProxyType.cs" />
<Compile Include="LuaLib\LuaLib.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="LuaBase.cs" />
<Compile Include="LuaFunction.cs" />
<Compile Include="LuaGlobalAttribute.cs" />
<Compile Include="LuaHideAttribute.cs" />
<Compile Include="LuaRegistrationHelper.cs" />
<Compile Include="LuaTable.cs" />
<Compile Include="LuaUserData.cs" />
<Compile Include="Extensions\GeneralExtensions.cs" />
<Compile Include="GenerateEventAssembly\LuaClassType.cs" />
<Compile Include="GenerateEventAssembly\ILuaGeneratedType.cs" />
<Compile Include="GenerateEventAssembly\DelegateGenerator.cs" />
<Compile Include="GenerateEventAssembly\ClassGenerator.cs" />
<Compile Include="GenerateEventAssembly\CodeGeneration.cs" />
<Compile Include="Event\EventCodes.cs" />
<Compile Include="Event\EventMasks.cs" />
<Compile Include="Event\LuaDebug.cs" />
<Compile Include="Event\DebugHookEventArgs.cs" />
<Compile Include="Event\HookExceptionEventArgs.cs" />
<Compile Include="Exceptions\LuaException.cs" />
<Compile Include="Exceptions\LuaScriptException.cs" />
<Compile Include="LuaLib\LuaEnums.cs" />
<Compile Include="LuaLib\References.cs" />
<Compile Include="LuaLib\LuaTypes.cs" />
<Compile Include="LuaLib\GCOption.cs" />
<Compile Include="LuaLib\PseudoIndex.cs" />
<Compile Include="Method\MethodCache.cs" />
<Compile Include="Method\MethodArgs.cs" />
<Compile Include="Method\LuaMethodWrapper.cs" />
<Compile Include="Method\EventHandlerContainer.cs" />
<Compile Include="Method\RegisterEventHandler.cs" />
<Compile Include="Method\LuaEventHandler.cs" />
<Compile Include="Method\LuaDelegate.cs" />
<Compile Include="Method\LuaClassHelper.cs" />
</ItemGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
<ItemGroup>
<ProjectReference Include="..\KopiLua\KopiLua.csproj">
<Project>{E8DDBC21-EF74-4ABA-9C49-BFC702BE25D8}</Project>
<Name>KopiLua</Name>
</ProjectReference>
</ItemGroup>
<ItemGroup>
<Folder Include="Extensions\" />
<Folder Include="GenerateEventAssembly\" />
<Folder Include="Event\" />
<Folder Include="Exceptions\" />
<Folder Include="Method\" />
</ItemGroup>
</Project>
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="4.0">
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">x86</Platform>
<ProductVersion>9.0.21022</ProductVersion>
<SchemaVersion>2.0</SchemaVersion>
<ProjectGuid>{F55CABBB-4108-4A39-94E1-581FD46DC021}</ProjectGuid>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>LuaInterface</RootNamespace>
<AssemblyName>LuaInterface</AssemblyName>
<ReleaseVersion>2.x</ReleaseVersion>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x86' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>..\..\Run\Debug</OutputPath>
<DefineConstants>DEBUG</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<PlatformTarget>x86</PlatformTarget>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x86' ">
<DebugType>none</DebugType>
<Optimize>true</Optimize>
<OutputPath>..\..\Run\Release</OutputPath>
<DefineConstants>RELEASE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<PlatformTarget>x86</PlatformTarget>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x64' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>..\..\Run\Debug_x64</OutputPath>
<DefineConstants>DEBUG</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<PlatformTarget>x64</PlatformTarget>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x64' ">
<DebugType>none</DebugType>
<Optimize>true</Optimize>
<OutputPath>..\..\Run\Release_x64</OutputPath>
<DefineConstants>RELEASE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<PlatformTarget>x64</PlatformTarget>
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
<Reference Include="System.Data" />
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="CheckType.cs" />
<Compile Include="Lua.cs" />
<Compile Include="Metatables.cs" />
<Compile Include="ObjectTranslator.cs" />
<Compile Include="ProxyType.cs" />
<Compile Include="LuaLib\LuaLib.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="LuaBase.cs" />
<Compile Include="LuaFunction.cs" />
<Compile Include="LuaGlobalAttribute.cs" />
<Compile Include="LuaHideAttribute.cs" />
<Compile Include="LuaRegistrationHelper.cs" />
<Compile Include="LuaTable.cs" />
<Compile Include="LuaUserData.cs" />
<Compile Include="Extensions\GeneralExtensions.cs" />
<Compile Include="GenerateEventAssembly\LuaClassType.cs" />
<Compile Include="GenerateEventAssembly\ILuaGeneratedType.cs" />
<Compile Include="GenerateEventAssembly\DelegateGenerator.cs" />
<Compile Include="GenerateEventAssembly\ClassGenerator.cs" />
<Compile Include="GenerateEventAssembly\CodeGeneration.cs" />
<Compile Include="Event\EventCodes.cs" />
<Compile Include="Event\EventMasks.cs" />
<Compile Include="Event\LuaDebug.cs" />
<Compile Include="Event\DebugHookEventArgs.cs" />
<Compile Include="Event\HookExceptionEventArgs.cs" />
<Compile Include="Exceptions\LuaException.cs" />
<Compile Include="Exceptions\LuaScriptException.cs" />
<Compile Include="LuaLib\LuaEnums.cs" />
<Compile Include="LuaLib\References.cs" />
<Compile Include="LuaLib\LuaTypes.cs" />
<Compile Include="LuaLib\GCOption.cs" />
<Compile Include="LuaLib\PseudoIndex.cs" />
<Compile Include="Method\MethodCache.cs" />
<Compile Include="Method\MethodArgs.cs" />
<Compile Include="Method\LuaMethodWrapper.cs" />
<Compile Include="Method\EventHandlerContainer.cs" />
<Compile Include="Method\RegisterEventHandler.cs" />
<Compile Include="Method\LuaEventHandler.cs" />
<Compile Include="Method\LuaDelegate.cs" />
<Compile Include="Method\LuaClassHelper.cs" />
</ItemGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
<ItemGroup>
<ProjectReference Include="..\KopiLua\KopiLua.csproj">
<Project>{E8DDBC21-EF74-4ABA-9C49-BFC702BE25D8}</Project>
<Name>KopiLua</Name>
</ProjectReference>
</ItemGroup>
<ItemGroup>
<Folder Include="Extensions\" />
<Folder Include="GenerateEventAssembly\" />
<Folder Include="Event\" />
<Folder Include="Exceptions\" />
<Folder Include="Method\" />
</ItemGroup>
</Project>
/*
* This file is part of LuaInterface.
*
* Copyright (C) 2003-2005 Fabio Mascarenhas de Queiroz.
* Copyright (C) 2009 Joshua Simmons <simmons.44@gmail.com>
* Copyright (C) 2012 Megax <http://megax.yeahunter.hu/>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
using System;
namespace LuaInterface
{
public enum GCOption : int
{
/// <summary>
/// Stops the garbage collector.
/// </summary>
Stop = 0,
/// <summary>
/// Restarts the garbage collector.
/// </summary>
Restart = 1,
/// <summary>
/// Performs a full garbage-collection cycle.
/// </summary>
Collect = 2,
/// <summary>
/// Returns the current amount of memory (in Kbytes) in use by KopiLua.Lua.
/// </summary>
Count = 3,
/// <summary>
/// Returns the remainder of dividing the current amount of bytes of memory in use by Lua by 1024.
/// </summary>
CountB = 4,
/// <summary>
/// Performs an incremental step of garbage collection. The step "size" is controlled by data (larger values mean more steps) in a non-specified way. ifyou want to control the step size you must experimentally tune the value of data. The function returns 1 ifthe step finished a garbage-collection cycle.
/// </summary>
Step = 5,
/// <summary>
/// Sets data as the new value for the pause (Controls how long the collector waits before starting a new cycle) of the collector (see §2.10). The function returns the previous value of the pause.
/// </summary>
SetPause = 6,
/// <summary>
/// Sets data as the new value for the step multiplier of the collector (Controls the relative speed of the collector relative to memory allocation.). The function returns the previous value of the step multiplier.
/// </summary>
SetStepMul = 7
}
/*
* This file is part of LuaInterface.
*
* Copyright (C) 2003-2005 Fabio Mascarenhas de Queiroz.
* Copyright (C) 2009 Joshua Simmons <simmons.44@gmail.com>
* Copyright (C) 2012 Megax <http://megax.yeahunter.hu/>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
using System;
namespace LuaInterface
{
public enum GCOption : int
{
/// <summary>
/// Stops the garbage collector.
/// </summary>
Stop = 0,
/// <summary>
/// Restarts the garbage collector.
/// </summary>
Restart = 1,
/// <summary>
/// Performs a full garbage-collection cycle.
/// </summary>
Collect = 2,
/// <summary>
/// Returns the current amount of memory (in Kbytes) in use by KopiLua.Lua.
/// </summary>
Count = 3,
/// <summary>
/// Returns the remainder of dividing the current amount of bytes of memory in use by Lua by 1024.
/// </summary>
CountB = 4,
/// <summary>
/// Performs an incremental step of garbage collection. The step "size" is controlled by data (larger values mean more steps) in a non-specified way. ifyou want to control the step size you must experimentally tune the value of data. The function returns 1 ifthe step finished a garbage-collection cycle.
/// </summary>
Step = 5,
/// <summary>
/// Sets data as the new value for the pause (Controls how long the collector waits before starting a new cycle) of the collector (see §2.10). The function returns the previous value of the pause.
/// </summary>
SetPause = 6,
/// <summary>
/// Sets data as the new value for the step multiplier of the collector (Controls the relative speed of the collector relative to memory allocation.). The function returns the previous value of the step multiplier.
/// </summary>
SetStepMul = 7
}
}
\ No newline at end of file
/*
* This file is part of LuaInterface.
*
* Copyright (C) 2003-2005 Fabio Mascarenhas de Queiroz.
* Copyright (C) 2009 Joshua Simmons <simmons.44@gmail.com>
* Copyright (C) 2012 Megax <http://megax.yeahunter.hu/>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
using System;
namespace LuaInterface
{
/// <summary>
/// Enumeration of basic lua globals.
/// </summary>
public enum LuaEnums : int
{
/// <summary>
/// Option for multiple returns in `lua_pcall' and `lua_call'
/// </summary>
MultiRet = -1,
/// <summary>
/// Everything is OK.
/// </summary>
Ok = 0,
/// <summary>
/// Thread status, Ok or Yield
/// </summary>
Yield = 1,
/// <summary>
/// A Runtime error.
/// </summary>
ErrorRun = 2,
/// <summary>
/// A syntax error.
/// </summary>
ErrorSyntax = 3,
/// <summary>
/// A memory allocation error. For such errors, Lua does not call the error handler function.
/// </summary>
ErrorMemory = 4,
/// <summary>
/// An error in the error handling function.
/// </summary>
ErrorError = 5,
/// <summary>
/// An extra error for file load errors when using luaL_loadfile.
/// </summary>
ErrorFile = 6
}
/*
* This file is part of LuaInterface.
*
* Copyright (C) 2003-2005 Fabio Mascarenhas de Queiroz.
* Copyright (C) 2009 Joshua Simmons <simmons.44@gmail.com>
* Copyright (C) 2012 Megax <http://megax.yeahunter.hu/>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
using System;
namespace LuaInterface
{
/// <summary>
/// Enumeration of basic lua globals.
/// </summary>
public enum LuaEnums : int
{
/// <summary>
/// Option for multiple returns in `lua_pcall' and `lua_call'
/// </summary>
MultiRet = -1,
/// <summary>
/// Everything is OK.
/// </summary>
Ok = 0,
/// <summary>
/// Thread status, Ok or Yield
/// </summary>
Yield = 1,
/// <summary>
/// A Runtime error.
/// </summary>
ErrorRun = 2,
/// <summary>
/// A syntax error.
/// </summary>
ErrorSyntax = 3,
/// <summary>
/// A memory allocation error. For such errors, Lua does not call the error handler function.
/// </summary>
ErrorMemory = 4,
/// <summary>
/// An error in the error handling function.
/// </summary>
ErrorError = 5,
/// <summary>
/// An extra error for file load errors when using luaL_loadfile.
/// </summary>
ErrorFile = 6
}
}
\ No newline at end of file
......@@ -126,29 +126,12 @@ namespace LuaInterface
return result;
}
/// <summary>
/// Pops the value referenced by reference by r in the table at index t onto the stack.
/// </summary>
/// <param name="state">
/// A <see cref="IntPtr"/>
/// </param>
/// <param name="t">
/// A stack index
/// </param>
/// <param name="r">
/// A <see cref="System.Int32"/>
/// </param>
public static void luaL_getref(LuaCore.lua_State state, int t, int r)
{
LuaCore.lua_rawgeti(state, t, r);
}
public static bool luaL_checkmetatable(LuaCore.lua_State luaState,int index)
{
bool retVal = false;
Console.WriteLine("v: " + luaState.tt.ToString());
if(LuaCore.lua_getmetatable(luaState,index)!=0)
if(LuaCore.lua_getmetatable(luaState,index) != 0)
{
LuaCore.lua_pushlightuserdata(luaState, tag);
LuaCore.lua_rawget(luaState, -2);
......@@ -174,13 +157,13 @@ namespace LuaInterface
LuaCore.luaL_unref(luaState, (int)PseudoIndex.Registry, reference);
}
public static int luanet_rawnetobj(LuaCore.lua_State luaState,int obj)
public static int luanet_rawnetobj(LuaCore.lua_State luaState, int obj)
{
int udata = (int)LuaCore.lua_touserdata2(luaState, obj);
return udata != 0 ? udata : -1;
}
public static void lua_pushstdcallcfunction(LuaCore.lua_State luaState,LuaCore.lua_CFunction function)
public static void lua_pushstdcallcfunction(LuaCore.lua_State luaState, LuaCore.lua_CFunction function)
{
lua_pushcfunction(luaState, function);
}
......@@ -192,7 +175,7 @@ namespace LuaInterface
if(p != 0)
{
/* value is a userdata? */
if(LuaCore.lua_getmetatable(luaState, ud)!=0)
if(LuaCore.lua_getmetatable(luaState, ud) != 0)
{
/* does it have a metatable? */
LuaCore.lua_getfield(luaState, (int)PseudoIndex.Registry, tname); /* get correct metatable */
......
/*
* This file is part of LuaInterface.
*
* Copyright (C) 2003-2005 Fabio Mascarenhas de Queiroz.
* Copyright (C) 2009 Joshua Simmons <simmons.44@gmail.com>
* Copyright (C) 2012 Megax <http://megax.yeahunter.hu/>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
using System;
using System.IO;
using System.Runtime.InteropServices;
using System.Runtime.Serialization.Formatters.Binary;
using LuaInterface.Extensions;
namespace LuaInterface
{
public enum LuaTypes : int
{
None = -1,
Nil = 0,
Boolean = 1,
LightUserdata = 2,
Number = 3,
String = 4,
Table = 5,
Function = 6,
UserData = 7,
Thread = 8
}
/*
* This file is part of LuaInterface.
*
* Copyright (C) 2003-2005 Fabio Mascarenhas de Queiroz.
* Copyright (C) 2009 Joshua Simmons <simmons.44@gmail.com>
* Copyright (C) 2012 Megax <http://megax.yeahunter.hu/>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
using System;
using System.IO;
using System.Runtime.InteropServices;
using System.Runtime.Serialization.Formatters.Binary;
using LuaInterface.Extensions;
namespace LuaInterface
{
public enum LuaTypes : int
{
None = -1,
Nil = 0,
Boolean = 1,
LightUserdata = 2,
Number = 3,
String = 4,
Table = 5,
Function = 6,
UserData = 7,
Thread = 8
}
}
\ No newline at end of file
/*
* This file is part of LuaInterface.
*
* Copyright (C) 2003-2005 Fabio Mascarenhas de Queiroz.
* Copyright (C) 2009 Joshua Simmons <simmons.44@gmail.com>
* Copyright (C) 2012 Megax <http://megax.yeahunter.hu/>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
using System;
namespace LuaInterface
{
public enum PseudoIndex : int
{
Registry = (-10000),
Environment = (-10001),
Globals = (-10002)
}
/*
* This file is part of LuaInterface.
*
* Copyright (C) 2003-2005 Fabio Mascarenhas de Queiroz.
* Copyright (C) 2009 Joshua Simmons <simmons.44@gmail.com>
* Copyright (C) 2012 Megax <http://megax.yeahunter.hu/>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
using System;
namespace LuaInterface
{
public enum PseudoIndex : int
{
Registry = (-10000),
Environment = (-10001),
Globals = (-10002)
}
}
\ No newline at end of file
/*
* This file is part of LuaInterface.
*
* Copyright (C) 2003-2005 Fabio Mascarenhas de Queiroz.
* Copyright (C) 2009 Joshua Simmons <simmons.44@gmail.com>
* Copyright (C) 2012 Megax <http://megax.yeahunter.hu/>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
using System;
namespace LuaInterface
{
public enum References : int
{
RefNil = -1,
NoRef = -2
}
/*
* This file is part of LuaInterface.
*
* Copyright (C) 2003-2005 Fabio Mascarenhas de Queiroz.
* Copyright (C) 2009 Joshua Simmons <simmons.44@gmail.com>
* Copyright (C) 2012 Megax <http://megax.yeahunter.hu/>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
using System;
namespace LuaInterface
{
public enum References : int
{
RefNil = -1,
NoRef = -2
}
}
\ No newline at end of file
/*
* This file is part of LuaInterface.
*
* Copyright (C) 2003-2005 Fabio Mascarenhas de Queiroz.
* Copyright (C) 2012 Megax <http://megax.yeahunter.hu/>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
using System;
using System.Reflection;
using System.Diagnostics.CodeAnalysis;
using LuaInterface.Extensions;
namespace LuaInterface
{
public static class LuaRegistrationHelper
{
#region Tagged instance methods
/// <summary>
/// Registers all public instance methods in an object tagged with <see cref="LuaGlobalAttribute"/> as Lua global functions
/// </summary>
/// <param name="lua">The Lua VM to add the methods to</param>
/// <param name="o">The object to get the methods from</param>
public static void TaggedInstanceMethods(Lua lua, object o)
{
#region Sanity checks
if(lua.IsNull())
throw new ArgumentNullException("lua");
if(o.IsNull())
throw new ArgumentNullException("o");
#endregion
foreach(var method in o.GetType().GetMethods(BindingFlags.Instance | BindingFlags.Public))
{
foreach(LuaGlobalAttribute attribute in method.GetCustomAttributes(typeof(LuaGlobalAttribute), true))
{
if(string.IsNullOrEmpty(attribute.Name))
lua.RegisterFunction(method.Name, o, method); // CLR name
else
lua.RegisterFunction(attribute.Name, o, method); // Custom name
}
}
}
#endregion
#region Tagged static methods
/// <summary>
/// Registers all public static methods in a class tagged with <see cref="LuaGlobalAttribute"/> as Lua global functions
/// </summary>
/// <param name="lua">The Lua VM to add the methods to</param>
/// <param name="type">The class type to get the methods from</param>
public static void TaggedStaticMethods(Lua lua, Type type)
{
#region Sanity checks
if(lua.IsNull())
throw new ArgumentNullException("lua");
if(type.IsNull())
throw new ArgumentNullException("type");
if(!type.IsClass)
throw new ArgumentException("The type must be a class!", "type");
#endregion
foreach(var method in type.GetMethods(BindingFlags.Static | BindingFlags.Public))
{
foreach(LuaGlobalAttribute attribute in method.GetCustomAttributes(typeof(LuaGlobalAttribute), false))
{
if(string.IsNullOrEmpty(attribute.Name))
lua.RegisterFunction(method.Name, null, method); // CLR name
else
lua.RegisterFunction(attribute.Name, null, method); // Custom name
}
}
}
#endregion
#region Enumeration
/// <summary>
/// Registers an enumeration's values for usage as a Lua variable table
/// </summary>
/// <typeparam name="T">The enum type to register</typeparam>
/// <param name="lua">The Lua VM to add the enum to</param>
[SuppressMessage("Microsoft.Design", "CA1004:GenericMethodsShouldProvideTypeParameter", Justification = "The type parameter is used to select an enum type")]
public static void Enumeration<T>(Lua lua)
{
#region Sanity checks
if(lua.IsNull())
throw new ArgumentNullException("lua");
#endregion
var type = typeof(T);
if(!type.IsEnum)
throw new ArgumentException("The type must be an enumeration!");
string[] names = Enum.GetNames(type);
var values = (T[])Enum.GetValues(type);
lua.NewTable(type.Name);
for(int i = 0; i < names.Length; i++)
{
string path = type.Name + "." + names[i];
lua[path] = values[i];
}
}
#endregion
}
/*
* This file is part of LuaInterface.
*
* Copyright (C) 2003-2005 Fabio Mascarenhas de Queiroz.
* Copyright (C) 2012 Megax <http://megax.yeahunter.hu/>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
using System;
using System.Reflection;
using System.Diagnostics.CodeAnalysis;
using LuaInterface.Extensions;
namespace LuaInterface
{
public static class LuaRegistrationHelper
{
#region Tagged instance methods
/// <summary>
/// Registers all public instance methods in an object tagged with <see cref="LuaGlobalAttribute"/> as Lua global functions
/// </summary>
/// <param name="lua">The Lua VM to add the methods to</param>
/// <param name="o">The object to get the methods from</param>
public static void TaggedInstanceMethods(Lua lua, object o)
{
#region Sanity checks
if(lua.IsNull())
throw new ArgumentNullException("lua");
if(o.IsNull())
throw new ArgumentNullException("o");
#endregion
foreach(var method in o.GetType().GetMethods(BindingFlags.Instance | BindingFlags.Public))
{
foreach(LuaGlobalAttribute attribute in method.GetCustomAttributes(typeof(LuaGlobalAttribute), true))
{
if(string.IsNullOrEmpty(attribute.Name))
lua.RegisterFunction(method.Name, o, method); // CLR name
else
lua.RegisterFunction(attribute.Name, o, method); // Custom name
}
}
}
#endregion
#region Tagged static methods
/// <summary>
/// Registers all public static methods in a class tagged with <see cref="LuaGlobalAttribute"/> as Lua global functions
/// </summary>
/// <param name="lua">The Lua VM to add the methods to</param>
/// <param name="type">The class type to get the methods from</param>
public static void TaggedStaticMethods(Lua lua, Type type)
{
#region Sanity checks
if(lua.IsNull())
throw new ArgumentNullException("lua");
if(type.IsNull())
throw new ArgumentNullException("type");
if(!type.IsClass)
throw new ArgumentException("The type must be a class!", "type");
#endregion
foreach(var method in type.GetMethods(BindingFlags.Static | BindingFlags.Public))
{
foreach(LuaGlobalAttribute attribute in method.GetCustomAttributes(typeof(LuaGlobalAttribute), false))
{
if(string.IsNullOrEmpty(attribute.Name))
lua.RegisterFunction(method.Name, null, method); // CLR name
else
lua.RegisterFunction(attribute.Name, null, method); // Custom name
}
}
}
#endregion
#region Enumeration
/// <summary>
/// Registers an enumeration's values for usage as a Lua variable table
/// </summary>
/// <typeparam name="T">The enum type to register</typeparam>
/// <param name="lua">The Lua VM to add the enum to</param>
[SuppressMessage("Microsoft.Design", "CA1004:GenericMethodsShouldProvideTypeParameter", Justification = "The type parameter is used to select an enum type")]
public static void Enumeration<T>(Lua lua)
{
#region Sanity checks
if(lua.IsNull())
throw new ArgumentNullException("lua");
#endregion
var type = typeof(T);
if(!type.IsEnum)
throw new ArgumentException("The type must be an enumeration!");
string[] names = Enum.GetNames(type);
var values = (T[])Enum.GetValues(type);
lua.NewTable(type.Name);
for(int i = 0; i < names.Length; i++)
{
string path = type.Name + "." + names[i];
lua[path] = values[i];
}
}
#endregion
}
}
\ No newline at end of file
/*
* This file is part of LuaInterface.
*
* Copyright (C) 2003-2005 Fabio Mascarenhas de Queiroz.
* Copyright (C) 2012 Megax <http://megax.yeahunter.hu/>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
using System;
using System.Text;
using System.Collections;
using System.Collections.Generic;
namespace LuaInterface
{
using LuaCore = KopiLua.Lua;
/*
* Wrapper class for Lua tables
*
* Author: Fabio Mascarenhas
* Version: 1.0
*/
public class LuaTable : LuaBase
{
public LuaTable(int reference, Lua interpreter)
{
_Reference = reference;
_Interpreter = interpreter;
}
/*
* Indexer for string fields of the table
*/
public object this[string field]
{
get
{
return _Interpreter.getObject(_Reference, field);
}
set
{
_Interpreter.setObject(_Reference, field, value);
}
}
/*
* Indexer for numeric fields of the table
*/
public object this[object field]
{
get
{
return _Interpreter.getObject(_Reference, field);
}
set
{
_Interpreter.setObject(_Reference, field, value);
}
}
public System.Collections.IDictionaryEnumerator GetEnumerator()
{
return _Interpreter.GetTableDict(this).GetEnumerator();
}
public ICollection Keys
{
get { return _Interpreter.GetTableDict(this).Keys; }
}
public ICollection Values
{
get { return _Interpreter.GetTableDict(this).Values; }
}
/*
* Gets an string fields of a table ignoring its metatable,
* if it exists
*/
internal object rawget(string field)
{
return _Interpreter.rawGetObject(_Reference, field);
}
internal object rawgetFunction(string field)
{
object obj = _Interpreter.rawGetObject(_Reference, field);
if(obj is LuaCore.lua_CFunction)
return new LuaFunction((LuaCore.lua_CFunction)obj, _Interpreter);
else
return obj;
}
/*
* Pushes this table into the Lua stack
*/
internal void push(LuaCore.lua_State luaState)
{
LuaLib.lua_getref(luaState, _Reference);
}
public override string ToString()
{
return "table";
}
}
/*
* This file is part of LuaInterface.
*
* Copyright (C) 2003-2005 Fabio Mascarenhas de Queiroz.
* Copyright (C) 2012 Megax <http://megax.yeahunter.hu/>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
using System;
using System.Text;
using System.Collections;
using System.Collections.Generic;
namespace LuaInterface
{
using LuaCore = KopiLua.Lua;
/*
* Wrapper class for Lua tables
*
* Author: Fabio Mascarenhas
* Version: 1.0
*/
public class LuaTable : LuaBase
{
public LuaTable(int reference, Lua interpreter)
{
_Reference = reference;
_Interpreter = interpreter;
}
/*
* Indexer for string fields of the table
*/
public object this[string field]
{
get
{
return _Interpreter.getObject(_Reference, field);
}
set
{
_Interpreter.setObject(_Reference, field, value);
}
}
/*
* Indexer for numeric fields of the table
*/
public object this[object field]
{
get
{
return _Interpreter.getObject(_Reference, field);
}
set
{
_Interpreter.setObject(_Reference, field, value);
}
}
public System.Collections.IDictionaryEnumerator GetEnumerator()
{
return _Interpreter.GetTableDict(this).GetEnumerator();
}
public ICollection Keys
{
get { return _Interpreter.GetTableDict(this).Keys; }
}
public ICollection Values
{
get { return _Interpreter.GetTableDict(this).Values; }
}
/*
* Gets an string fields of a table ignoring its metatable,
* if it exists
*/
internal object rawget(string field)
{
return _Interpreter.rawGetObject(_Reference, field);
}
internal object rawgetFunction(string field)
{
object obj = _Interpreter.rawGetObject(_Reference, field);
if(obj is LuaCore.lua_CFunction)
return new LuaFunction((LuaCore.lua_CFunction)obj, _Interpreter);
else
return obj;
}
/*
* Pushes this table into the Lua stack
*/
internal void push(LuaCore.lua_State luaState)
{
LuaLib.lua_getref(luaState, _Reference);
}
public override string ToString()
{
return "table";
}
}
}
\ No newline at end of file
/*
* This file is part of LuaInterface.
*
* Copyright (C) 2003-2005 Fabio Mascarenhas de Queiroz.
* Copyright (C) 2012 Megax <http://megax.yeahunter.hu/>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
using System;
using System.Text;
using System.Collections.Generic;
namespace LuaInterface
{
using LuaCore = KopiLua.Lua;
public class LuaUserData : LuaBase
{
public LuaUserData(int reference, Lua interpreter)
{
_Reference = reference;
_Interpreter = interpreter;
}
/*
* Indexer for string fields of the userdata
*/
public object this[string field]
{
get
{
return _Interpreter.getObject(_Reference, field);
}
set
{
_Interpreter.setObject(_Reference, field, value);
}
}
/*
* Indexer for numeric fields of the userdata
*/
public object this[object field]
{
get
{
return _Interpreter.getObject(_Reference, field);
}
set
{
_Interpreter.setObject(_Reference, field, value);
}
}
/*
* Calls the userdata and returns its return values inside
* an array
*/
public object[] Call(params object[] args)
{
return _Interpreter.callFunction(this, args);
}
/*
* Pushes the userdata into the Lua stack
*/
internal void push(LuaCore.lua_State luaState)
{
LuaLib.lua_getref(luaState, _Reference);
}
public override string ToString()
{
return "userdata";
}
}
/*
* This file is part of LuaInterface.
*
* Copyright (C) 2003-2005 Fabio Mascarenhas de Queiroz.
* Copyright (C) 2012 Megax <http://megax.yeahunter.hu/>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
using System;
using System.Text;
using System.Collections.Generic;
namespace LuaInterface
{
using LuaCore = KopiLua.Lua;
public class LuaUserData : LuaBase
{
public LuaUserData(int reference, Lua interpreter)
{
_Reference = reference;
_Interpreter = interpreter;
}
/*
* Indexer for string fields of the userdata
*/
public object this[string field]
{
get
{
return _Interpreter.getObject(_Reference, field);
}
set
{
_Interpreter.setObject(_Reference, field, value);
}
}
/*
* Indexer for numeric fields of the userdata
*/
public object this[object field]
{
get
{
return _Interpreter.getObject(_Reference, field);
}
set
{
_Interpreter.setObject(_Reference, field, value);
}
}
/*
* Calls the userdata and returns its return values inside
* an array
*/
public object[] Call(params object[] args)
{
return _Interpreter.callFunction(this, args);
}
/*
* Pushes the userdata into the Lua stack
*/
internal void push(LuaCore.lua_State luaState)
{
LuaLib.lua_getref(luaState, _Reference);
}
public override string ToString()
{
return "userdata";
}
}
}
\ No newline at end of file
/*
* This file is part of LuaInterface.
*
* Copyright (C) 2003-2005 Fabio Mascarenhas de Queiroz.
* Copyright (C) 2012 Megax <http://megax.yeahunter.hu/>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
using System;
using System.IO;
using System.Collections;
using System.Reflection;
using System.Diagnostics;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using LuaInterface.Method;
using LuaInterface.Extensions;
namespace LuaInterface
{
using LuaCore = KopiLua.Lua;
/*
* Functions used in the metatables of userdata representing
* CLR objects
*
* Author: Fabio Mascarenhas
* Version: 1.0
*/
class MetaFunctions
{
internal LuaCore.lua_CFunction gcFunction, indexFunction, newindexFunction, baseIndexFunction,
classIndexFunction, classNewindexFunction, execDelegateFunction, callConstructorFunction, toStringFunction;
private Hashtable memberCache = new Hashtable();
private ObjectTranslator translator;
/*
* __index metafunction for CLR objects. Implemented in Lua.
*/
internal static string luaIndexFunction =
"local function index(obj,name) \n" +
" local meta=getmetatable(obj) \n" +
" local cached=meta.cache[name] \n" +
" if cached~=nil then \n" +
" return cached \n" +
" else \n" +
" local value,isFunc=get_object_member(obj,name) \n" +
" if isFunc then \n" +
" meta.cache[name]=value \n" +
" end \n" +
" return value \n" +
" end \n" +
"end \n" +
"return index ";
public MetaFunctions(ObjectTranslator translator)
{
this.translator = translator;
gcFunction = new LuaCore.lua_CFunction(this.collectObject);
toStringFunction = new LuaCore.lua_CFunction(this.toString);
indexFunction = new LuaCore.lua_CFunction(this.getMethod);
newindexFunction = new LuaCore.lua_CFunction(this.setFieldOrProperty);
baseIndexFunction = new LuaCore.lua_CFunction(this.getBaseMethod);
callConstructorFunction = new LuaCore.lua_CFunction(this.callConstructor);
classIndexFunction = new LuaCore.lua_CFunction(this.getClassMethod);
classNewindexFunction = new LuaCore.lua_CFunction(this.setClassFieldOrProperty);
execDelegateFunction = new LuaCore.lua_CFunction(this.runFunctionDelegate);
}
/*
* __call metafunction of CLR delegates, retrieves and calls the delegate.
*/
private int runFunctionDelegate(LuaCore.lua_State luaState)
{
LuaCore.lua_CFunction func = (LuaCore.lua_CFunction)translator.getRawNetObject(luaState, 1);
LuaCore.lua_remove(luaState, 1);
return func(luaState);
}
/*
* __gc metafunction of CLR objects.
*/
private int collectObject(LuaCore.lua_State luaState)
{
int udata = LuaLib.luanet_rawnetobj(luaState, 1);
if(udata != -1)
translator.collectObject(udata);
else
{
// Debug.WriteLine("not found: " + udata);
}
return 0;
}
/*
* __tostring metafunction of CLR objects.
*/
private int toString(LuaCore.lua_State luaState)
{
object obj = translator.getRawNetObject(luaState, 1);
if(!obj.IsNull())
translator.push(luaState, obj.ToString() + ": " + obj.GetHashCode());
else
LuaCore.lua_pushnil(luaState);
return 1;
}
/// <summary>
/// Debug tool to dump the lua stack
/// </summary>
/// FIXME, move somewhere else
public static void dumpStack(ObjectTranslator translator, LuaCore.lua_State luaState)
{
int depth = LuaCore.lua_gettop(luaState);
Debug.WriteLine("lua stack depth: " + depth);
for(int i = 1; i <= depth; i++)
{
var type = LuaCore.lua_type(luaState, i).ToLuaTypes();
// we dump stacks when deep in calls, calling typename while the stack is in flux can fail sometimes, so manually check for key types
string typestr = (type == LuaTypes.Table) ? "table" : LuaCore.lua_typename(luaState, (int)type).ToString();
string strrep = LuaCore.lua_tostring(luaState, i).ToString();
if(type == LuaTypes.UserData)
{
object obj = translator.getRawNetObject(luaState, i);
strrep = obj.ToString();
}
Debug.Print("{0}: ({1}) {2}", i, typestr, strrep);
}
}
/*
* Called by the __index metafunction of CLR objects in case the
* method is not cached or it is a field/property/event.
* Receives the object and the member name as arguments and returns
* either the value of the member or a delegate to call it.
* If the member does not exist returns nil.
*/
private int getMethod(LuaCore.lua_State luaState)
{
object obj = translator.getRawNetObject(luaState, 1);
if(obj.IsNull())
{
translator.throwError(luaState, "trying to index an invalid object reference");
LuaCore.lua_pushnil(luaState);
return 1;
}
object index = translator.getObject(luaState, 2);
var indexType = index.GetType();
string methodName = index as string; // will be null if not a string arg
var objType = obj.GetType();
// Handle the most common case, looking up the method by name.
// CP: This will fail when using indexers and attempting to get a value with the same name as a property of the object,
// ie: xmlelement['item'] <- item is a property of xmlelement
try
{
if(!methodName.IsNull() && isMemberPresent(objType, methodName))
return getMember(luaState, objType, obj, methodName, BindingFlags.Instance | BindingFlags.IgnoreCase);
}
catch
{
}
// Try to access by array if the type is right and index is an int (lua numbers always come across as double)
if(objType.IsArray && index is double)
{
int intIndex = (int)((double)index);
if(objType.UnderlyingSystemType == typeof(float[]))
{
float[] arr = ((float[])obj);
translator.push(luaState, arr[intIndex]);
}
else if(objType.UnderlyingSystemType == typeof(double[]))
{
double[] arr = ((double[])obj);
translator.push(luaState, arr[intIndex]);
}
else if(objType.UnderlyingSystemType == typeof(int[]))
{
int[] arr = ((int[])obj);
translator.push(luaState, arr[intIndex]);
}
else
{
object[] arr = (object[])obj;
translator.push(luaState, arr[intIndex]);
}
}
else
{
// Try to use get_Item to index into this .net object
//MethodInfo getter = objType.GetMethod("get_Item");
var methods = objType.GetMethods();
foreach(var mInfo in methods)
{
if(mInfo.Name == "get_Item")
{
//check if the signature matches the input
if(mInfo.GetParameters().Length == 1)
{
var getter = mInfo;
var actualParms = (!getter.IsNull()) ? getter.GetParameters() : null;
if(actualParms.IsNull() || actualParms.Length != 1)
{
translator.throwError(luaState, "method not found (or no indexer): " + index);
LuaCore.lua_pushnil(luaState);
}
else
{
// Get the index in a form acceptable to the getter
index = translator.getAsType(luaState, 2, actualParms[0].ParameterType);
object[] args = new object[1];
// Just call the indexer - if out of bounds an exception will happen
args[0] = index;
try
{
object result = getter.Invoke(obj, args);
translator.push(luaState, result);
}
catch(TargetInvocationException e)
{
// Provide a more readable description for the common case of key not found
if(e.InnerException is KeyNotFoundException)
translator.throwError(luaState, "key '" + index + "' not found ");
else
translator.throwError(luaState, "exception indexing '" + index + "' " + e.Message);
LuaCore.lua_pushnil(luaState);
}
}
}
}
}
}
LuaCore.lua_pushboolean(luaState, 0);
return 2;
}
/*
* __index metafunction of base classes (the base field of Lua tables).
* Adds a prefix to the method name to call the base version of the method.
*/
private int getBaseMethod(LuaCore.lua_State luaState)
{
object obj = translator.getRawNetObject(luaState, 1);
if(obj.IsNull())
{
translator.throwError(luaState, "trying to index an invalid object reference");
LuaCore.lua_pushnil(luaState);
LuaCore.lua_pushboolean(luaState, 0);
return 2;
}
string methodName = LuaCore.lua_tostring(luaState, 2).ToString();
if(methodName.IsNull())
{
LuaCore.lua_pushnil(luaState);
LuaCore.lua_pushboolean(luaState, 0);
return 2;
}
getMember(luaState, obj.GetType(), obj, "__luaInterface_base_" + methodName, BindingFlags.Instance | BindingFlags.IgnoreCase);
LuaCore.lua_settop(luaState, -2);
if(LuaCore.lua_type(luaState, -1).ToLuaTypes() == LuaTypes.Nil)
{
LuaCore.lua_settop(luaState, -2);
return getMember(luaState, obj.GetType(), obj, methodName, BindingFlags.Instance | BindingFlags.IgnoreCase);
}
LuaCore.lua_pushboolean(luaState, 0);
return 2;
}
/// <summary>
/// Does this method exist as either an instance or static?
/// </summary>
/// <param name="objType"></param>
/// <param name="methodName"></param>
/// <returns></returns>
bool isMemberPresent(IReflect objType, string methodName)
{
object cachedMember = checkMemberCache(memberCache, objType, methodName);
if(!cachedMember.IsNull())
return true;
//CP: Removed NonPublic binding search
var members = objType.GetMember(methodName, BindingFlags.Static | BindingFlags.Instance | BindingFlags.Public | BindingFlags.IgnoreCase/* | BindingFlags.NonPublic*/);
return (members.Length > 0);
}
/*
* Pushes the value of a member or a delegate to call it, depending on the type of
* the member. Works with static or instance members.
* Uses reflection to find members, and stores the reflected MemberInfo object in
* a cache (indexed by the type of the object and the name of the member).
*/
private int getMember(LuaCore.lua_State luaState, IReflect objType, object obj, string methodName, BindingFlags bindingType)
{
bool implicitStatic = false;
MemberInfo member = null;
object cachedMember = checkMemberCache(memberCache, objType, methodName);
//object cachedMember=null;
if(cachedMember is LuaCore.lua_CFunction)
{
translator.pushFunction(luaState, (LuaCore.lua_CFunction)cachedMember);
translator.push(luaState, true);
return 2;
}
else if(!cachedMember.IsNull())
member = (MemberInfo)cachedMember;
else
{
//CP: Removed NonPublic binding search
var members = objType.GetMember(methodName, bindingType | BindingFlags.Public | BindingFlags.IgnoreCase/*| BindingFlags.NonPublic*/);
if(members.Length > 0)
member = members[0];
else
{
// If we can't find any suitable instance members, try to find them as statics - but we only want to allow implicit static
// lookups for fields/properties/events -kevinh
//CP: Removed NonPublic binding search and made case insensitive
members = objType.GetMember(methodName, bindingType | BindingFlags.Static | BindingFlags.Public | BindingFlags.IgnoreCase/*| BindingFlags.NonPublic*/);
if(members.Length > 0)
{
member = members[0];
implicitStatic = true;
}
}
}
if(!member.IsNull())
{
if(member.MemberType == MemberTypes.Field)
{
var field = (FieldInfo)member;
if(cachedMember.IsNull())
setMemberCache(memberCache, objType, methodName, member);
try
{
translator.push(luaState, field.GetValue(obj));
}
catch
{
LuaCore.lua_pushnil(luaState);
}
}
else if(member.MemberType == MemberTypes.Property)
{
var property = (PropertyInfo)member;
if(cachedMember.IsNull())
setMemberCache(memberCache, objType, methodName, member);
try
{
object val = property.GetValue(obj, null);
translator.push(luaState, val);
}
catch(ArgumentException)
{
// If we can't find the getter in our class, recurse up to the base class and see
// if they can help.
if(objType is Type && !(((Type)objType) == typeof(object)))
return getMember(luaState, ((Type)objType).BaseType, obj, methodName, bindingType);
else
LuaCore.lua_pushnil(luaState);
}
catch(TargetInvocationException e) // Convert this exception into a Lua error
{
ThrowError(luaState, e);
LuaCore.lua_pushnil(luaState);
}
}
else if(member.MemberType == MemberTypes.Event)
{
var eventInfo = (EventInfo)member;
if(cachedMember.IsNull())
setMemberCache(memberCache, objType, methodName, member);
translator.push(luaState, new RegisterEventHandler(translator.pendingEvents, obj, eventInfo));
}
else if(!implicitStatic)
{
if(member.MemberType == MemberTypes.NestedType)
{
// kevinh - added support for finding nested types
// cache us
if(cachedMember.IsNull())
setMemberCache(memberCache, objType, methodName, member);
// Find the name of our class
string name = member.Name;
var dectype = member.DeclaringType;
// Build a new long name and try to find the type by name
string longname = dectype.FullName + "+" + name;
var nestedType = translator.FindType(longname);
translator.pushType(luaState, nestedType);
}
else
{
// Member type must be 'method'
var wrapper = new LuaCore.lua_CFunction((new LuaMethodWrapper(translator, objType, methodName, bindingType)).call);
if(cachedMember.IsNull())
setMemberCache(memberCache, objType, methodName, wrapper);
translator.pushFunction(luaState, wrapper);
translator.push(luaState, true);
return 2;
}
}
else
{
// If we reach this point we found a static method, but can't use it in this context because the user passed in an instance
translator.throwError(luaState, "can't pass instance to static method " + methodName);
LuaCore.lua_pushnil(luaState);
}
}
else
{
// kevinh - we want to throw an exception because meerly returning 'nil' in this case
// is not sufficient. valid data members may return nil and therefore there must be some
// way to know the member just doesn't exist.
translator.throwError(luaState, "unknown member name " + methodName);
LuaCore.lua_pushnil(luaState);
}
// push false because we are NOT returning a function (see luaIndexFunction)
translator.push(luaState, false);
return 2;
}
/*
* Checks if a MemberInfo object is cached, returning it or null.
*/
private object checkMemberCache(Hashtable memberCache, IReflect objType, string memberName)
{
var members = (Hashtable)memberCache[objType];
return !members.IsNull() ? members[memberName] : null;
}
/*
* Stores a MemberInfo object in the member cache.
*/
private void setMemberCache(Hashtable memberCache, IReflect objType, string memberName, object member)
{
var members = (Hashtable)memberCache[objType];
if(members.IsNull())
{
members = new Hashtable();
memberCache[objType] = members;
}
members[memberName] = member;
}
/*
* __newindex metafunction of CLR objects. Receives the object,
* the member name and the value to be stored as arguments. Throws
* and error if the assignment is invalid.
*/
private int setFieldOrProperty(LuaCore.lua_State luaState)
{
object target = translator.getRawNetObject(luaState, 1);
if(target.IsNull())
{
translator.throwError(luaState, "trying to index and invalid object reference");
return 0;
}
var type = target.GetType();
// First try to look up the parameter as a property name
string detailMessage;
bool didMember = trySetMember(luaState, type, target, BindingFlags.Instance | BindingFlags.IgnoreCase, out detailMessage);
if(didMember)
return 0; // Must have found the property name
// We didn't find a property name, now see if we can use a [] style this accessor to set array contents
try
{
if(type.IsArray && LuaCore.lua_isnumber(luaState, 2).ToBoolean())
{
int index = (int)LuaCore.lua_tonumber(luaState, 2);
var arr = (Array)target;
object val = translator.getAsType(luaState, 3, arr.GetType().GetElementType());
arr.SetValue(val, index);
}
else
{
// Try to see if we have a this[] accessor
var setter = type.GetMethod("set_Item");
if(!setter.IsNull())
{
var args = setter.GetParameters();
var valueType = args[1].ParameterType;
// The new val ue the user specified
object val = translator.getAsType(luaState, 3, valueType);
var indexType = args[0].ParameterType;
object index = translator.getAsType(luaState, 2, indexType);
object[] methodArgs = new object[2];
// Just call the indexer - if out of bounds an exception will happen
methodArgs[0] = index;
methodArgs[1] = val;
setter.Invoke(target, methodArgs);
}
else
translator.throwError(luaState, detailMessage); // Pass the original message from trySetMember because it is probably best
}
}
catch(SEHException)
{
// If we are seeing a C++ exception - this must actually be for Lua's private use. Let it handle it
throw;
}
catch(Exception e)
{
ThrowError(luaState, e);
}
return 0;
}
/// <summary>
/// Tries to set a named property or field
/// </summary>
/// <param name="luaState"></param>
/// <param name="targetType"></param>
/// <param name="target"></param>
/// <param name="bindingType"></param>
/// <returns>false if unable to find the named member, true for success</returns>
private bool trySetMember(LuaCore.lua_State luaState, IReflect targetType, object target, BindingFlags bindingType, out string detailMessage)
{
detailMessage = null; // No error yet
// If not already a string just return - we don't want to call tostring - which has the side effect of
// changing the lua typecode to string
// Note: We don't use isstring because the standard lua C isstring considers either strings or numbers to
// be true for isstring.
if(LuaCore.lua_type(luaState, 2).ToLuaTypes() != LuaTypes.String)
{
detailMessage = "property names must be strings";
return false;
}
// We only look up property names by string
string fieldName = LuaCore.lua_tostring(luaState, 2).ToString();
if(fieldName.IsNull() || fieldName.Length < 1 || !(char.IsLetter(fieldName[0]) || fieldName[0] == '_'))
{
detailMessage = "invalid property name";
return false;
}
// Find our member via reflection or the cache
var member = (MemberInfo)checkMemberCache(memberCache, targetType, fieldName);
if(member.IsNull())
{
//CP: Removed NonPublic binding search and made case insensitive
var members = targetType.GetMember(fieldName, bindingType | BindingFlags.Public | BindingFlags.IgnoreCase/*| BindingFlags.NonPublic*/);
if(members.Length > 0)
{
member = members[0];
setMemberCache(memberCache, targetType, fieldName, member);
}
else
{
detailMessage = "field or property '" + fieldName + "' does not exist";
return false;
}
}
if(member.MemberType == MemberTypes.Field)
{
var field = (FieldInfo)member;
object val = translator.getAsType(luaState, 3, field.FieldType);
try
{
field.SetValue(target, val);
}
catch (Exception e)
{
ThrowError(luaState, e);
}
// We did a call
return true;
}
else if(member.MemberType == MemberTypes.Property)
{
var property = (PropertyInfo)member;
object val = translator.getAsType(luaState, 3, property.PropertyType);
try
{
property.SetValue(target, val, null);
}
catch (Exception e)
{
ThrowError(luaState, e);
}
// We did a call
return true;
}
detailMessage = "'" + fieldName + "' is not a .net field or property";
return false;
}
/*
* Writes to fields or properties, either static or instance. Throws an error
* if the operation is invalid.
*/
private int setMember(LuaCore.lua_State luaState, IReflect targetType, object target, BindingFlags bindingType)
{
string detail;
bool success = trySetMember(luaState, targetType, target, bindingType, out detail);
if(!success)
translator.throwError(luaState, detail);
return 0;
}
/// <summary>
/// Convert a C# exception into a Lua error
/// </summary>
/// <param name="e"></param>
/// We try to look into the exception to give the most meaningful description
void ThrowError(LuaCore.lua_State luaState, Exception e)
{
// If we got inside a reflection show what really happened
var te = e as TargetInvocationException;
if (!te.IsNull())
e = te.InnerException;
translator.throwError(luaState, e);
}
/*
* __index metafunction of type references, works on static members.
*/
private int getClassMethod(LuaCore.lua_State luaState)
{
IReflect klass;
object obj = translator.getRawNetObject(luaState, 1);
if(obj.IsNull() || !(obj is IReflect))
{
translator.throwError(luaState, "trying to index an invalid type reference");
LuaCore.lua_pushnil(luaState);
return 1;
}
else
klass = (IReflect)obj;
if(LuaCore.lua_isnumber(luaState, 2).ToBoolean())
{
int size = (int)LuaCore.lua_tonumber(luaState, 2);
translator.push(luaState, Array.CreateInstance(klass.UnderlyingSystemType, size));
return 1;
}
else
{
string methodName = LuaCore.lua_tostring(luaState, 2).ToString();
if(methodName.IsNull())
{
LuaCore.lua_pushnil(luaState);
return 1;
} //CP: Ignore case
else
return getMember(luaState, klass, null, methodName, BindingFlags.FlattenHierarchy | BindingFlags.Static | BindingFlags.IgnoreCase);
}
}
/*
* __newindex function of type references, works on static members.
*/
private int setClassFieldOrProperty(LuaCore.lua_State luaState)
{
IReflect target;
object obj = translator.getRawNetObject(luaState, 1);
if(obj.IsNull() || !(obj is IReflect))
{
translator.throwError(luaState, "trying to index an invalid type reference");
return 0;
}
else
target = (IReflect)obj;
return setMember(luaState, target, null, BindingFlags.FlattenHierarchy | BindingFlags.Static | BindingFlags.IgnoreCase);
}
/*
* __call metafunction of type references. Searches for and calls
* a constructor for the type. Returns nil if the constructor is not
* found or if the arguments are invalid. Throws an error if the constructor
* generates an exception.
*/
private int callConstructor(LuaCore.lua_State luaState)
{
var validConstructor = new MethodCache();
IReflect klass;
object obj = translator.getRawNetObject(luaState, 1);
if(obj.IsNull() || !(obj is IReflect))
{
translator.throwError(luaState, "trying to call constructor on an invalid type reference");
LuaCore.lua_pushnil(luaState);
return 1;
}
else
klass = (IReflect)obj;
LuaCore.lua_remove(luaState, 1);
var constructors = klass.UnderlyingSystemType.GetConstructors();
foreach(var constructor in constructors)
{
bool isConstructor = matchParameters(luaState, constructor, ref validConstructor);
if(isConstructor)
{
try
{
translator.push(luaState, constructor.Invoke(validConstructor.args));
}
catch(TargetInvocationException e)
{
ThrowError(luaState, e);
LuaCore.lua_pushnil(luaState);
}
catch
{
LuaCore.lua_pushnil(luaState);
}
return 1;
}
}
string constructorName = (constructors.Length == 0) ? "unknown" : constructors[0].Name;
translator.throwError(luaState, String.Format("{0} does not contain constructor({1}) argument match",
klass.UnderlyingSystemType, constructorName));
LuaCore.lua_pushnil(luaState);
return 1;
}
/*
* Matches a method against its arguments in the Lua stack. Returns
* if the match was succesful. It it was also returns the information
* necessary to invoke the method.
*/
internal bool matchParameters(LuaCore.lua_State luaState, MethodBase method, ref MethodCache methodCache)
{
ExtractValue extractValue;
bool isMethod = true;
var paramInfo = method.GetParameters();
int currentLuaParam = 1;
int nLuaParams = LuaCore.lua_gettop(luaState);
var paramList = new ArrayList();
var outList = new List<int>();
var argTypes = new List<MethodArgs>();
foreach(var currentNetParam in paramInfo)
{
if(!currentNetParam.IsIn && currentNetParam.IsOut) // Skips out params
outList.Add(paramList.Add(null));
else if(currentLuaParam > nLuaParams) // Adds optional parameters
{
if(currentNetParam.IsOptional)
paramList.Add(currentNetParam.DefaultValue);
else
{
isMethod = false;
break;
}
}
else if(_IsTypeCorrect(luaState, currentLuaParam, currentNetParam, out extractValue)) // Type checking
{
int index = paramList.Add(extractValue(luaState, currentLuaParam));
var methodArg = new MethodArgs();
methodArg.index = index;
methodArg.extractValue = extractValue;
argTypes.Add(methodArg);
if(currentNetParam.ParameterType.IsByRef)
outList.Add(index);
currentLuaParam++;
} // Type does not match, ignore if the parameter is optional
else if(_IsParamsArray(luaState, currentLuaParam, currentNetParam, out extractValue))
{
object luaParamValue = extractValue(luaState, currentLuaParam);
var paramArrayType = currentNetParam.ParameterType.GetElementType();
Array paramArray;
if(luaParamValue is LuaTable)
{
var table = (LuaTable)luaParamValue;
var tableEnumerator = table.GetEnumerator();
paramArray = Array.CreateInstance(paramArrayType, table.Values.Count);
tableEnumerator.Reset();
int paramArrayIndex = 0;
while(tableEnumerator.MoveNext())
{
paramArray.SetValue(Convert.ChangeType(tableEnumerator.Value, currentNetParam.ParameterType.GetElementType()), paramArrayIndex);
paramArrayIndex++;
}
}
else
{
paramArray = Array.CreateInstance(paramArrayType, 1);
paramArray.SetValue(luaParamValue, 0);
}
int index = paramList.Add(paramArray);
var methodArg = new MethodArgs();
methodArg.index = index;
methodArg.extractValue = extractValue;
methodArg.isParamsArray = true;
methodArg.paramsArrayType = paramArrayType;
argTypes.Add(methodArg);
currentLuaParam++;
}
else if(currentNetParam.IsOptional)
paramList.Add(currentNetParam.DefaultValue);
else // No match
{
isMethod = false;
break;
}
}
if(currentLuaParam != nLuaParams + 1) // Number of parameters does not match
isMethod = false;
if(isMethod)
{
methodCache.args = paramList.ToArray();
methodCache.cachedMethod = method;
methodCache.outList = outList.ToArray();
methodCache.argTypes = argTypes.ToArray();
}
return isMethod;
}
/// <summary>
/// CP: Fix for operator overloading failure
/// Returns true if the type is set and assigns the extract value
/// </summary>
/// <param name="luaState"></param>
/// <param name="currentLuaParam"></param>
/// <param name="currentNetParam"></param>
/// <param name="extractValue"></param>
/// <returns></returns>
private bool _IsTypeCorrect(LuaCore.lua_State luaState, int currentLuaParam, ParameterInfo currentNetParam, out ExtractValue extractValue)
{
try
{
return (extractValue = translator.typeChecker.checkType(luaState, currentLuaParam, currentNetParam.ParameterType)) != null;
}
catch
{
extractValue = null;
Debug.WriteLine("Type wasn't correct");
return false;
}
}
private bool _IsParamsArray(LuaCore.lua_State luaState, int currentLuaParam, ParameterInfo currentNetParam, out ExtractValue extractValue)
{
extractValue = null;
if (currentNetParam.GetCustomAttributes(typeof(ParamArrayAttribute), false).Length > 0)
{
LuaTypes luaType;
try
{
luaType = LuaCore.lua_type(luaState, currentLuaParam).ToLuaTypes();
}
catch(Exception ex)
{
Debug.WriteLine("Could not retrieve lua type while attempting to determine params Array Status.");
Debug.WriteLine(ex.Message);
extractValue = null;
return false;
}
if(luaType == LuaTypes.Table)
{
try
{
extractValue = translator.typeChecker.getExtractor(typeof(LuaTable));
}
catch(Exception/* ex*/)
{
Debug.WriteLine("An error occurred during an attempt to retrieve a LuaTable extractor while checking for params array status.");
}
if(!extractValue.IsNull())
{
return true;
}
}
else
{
var paramElementType = currentNetParam.ParameterType.GetElementType();
try
{
extractValue = translator.typeChecker.checkType(luaState, currentLuaParam, paramElementType);
}
catch (Exception/* ex*/)
{
Debug.WriteLine(string.Format("An error occurred during an attempt to retrieve an extractor ({0}) while checking for params array status.", paramElementType.FullName));
}
if(!extractValue.IsNull())
{
return true;
}
}
}
Debug.WriteLine("Type wasn't Params object.");
return false;
}
}
/*
* This file is part of LuaInterface.
*
* Copyright (C) 2003-2005 Fabio Mascarenhas de Queiroz.
* Copyright (C) 2012 Megax <http://megax.yeahunter.hu/>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
using System;
using System.IO;
using System.Collections;
using System.Reflection;
using System.Diagnostics;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using LuaInterface.Method;
using LuaInterface.Extensions;
namespace LuaInterface
{
using LuaCore = KopiLua.Lua;
/*
* Functions used in the metatables of userdata representing
* CLR objects
*
* Author: Fabio Mascarenhas
* Version: 1.0
*/
class MetaFunctions
{
internal LuaCore.lua_CFunction gcFunction, indexFunction, newindexFunction, baseIndexFunction,
classIndexFunction, classNewindexFunction, execDelegateFunction, callConstructorFunction, toStringFunction;
private Hashtable memberCache = new Hashtable();
private ObjectTranslator translator;
/*
* __index metafunction for CLR objects. Implemented in Lua.
*/
internal static string luaIndexFunction =
"local function index(obj,name) \n" +
" local meta=getmetatable(obj) \n" +
" local cached=meta.cache[name] \n" +
" if cached~=nil then \n" +
" return cached \n" +
" else \n" +
" local value,isFunc=get_object_member(obj,name) \n" +
" if isFunc then \n" +
" meta.cache[name]=value \n" +
" end \n" +
" return value \n" +
" end \n" +
"end \n" +
"return index ";
public MetaFunctions(ObjectTranslator translator)
{
this.translator = translator;
gcFunction = new LuaCore.lua_CFunction(this.collectObject);
toStringFunction = new LuaCore.lua_CFunction(this.toString);
indexFunction = new LuaCore.lua_CFunction(this.getMethod);
newindexFunction = new LuaCore.lua_CFunction(this.setFieldOrProperty);
baseIndexFunction = new LuaCore.lua_CFunction(this.getBaseMethod);
callConstructorFunction = new LuaCore.lua_CFunction(this.callConstructor);
classIndexFunction = new LuaCore.lua_CFunction(this.getClassMethod);
classNewindexFunction = new LuaCore.lua_CFunction(this.setClassFieldOrProperty);
execDelegateFunction = new LuaCore.lua_CFunction(this.runFunctionDelegate);
}
/*
* __call metafunction of CLR delegates, retrieves and calls the delegate.
*/
private int runFunctionDelegate(LuaCore.lua_State luaState)
{
LuaCore.lua_CFunction func = (LuaCore.lua_CFunction)translator.getRawNetObject(luaState, 1);
LuaCore.lua_remove(luaState, 1);
return func(luaState);
}
/*
* __gc metafunction of CLR objects.
*/
private int collectObject(LuaCore.lua_State luaState)
{
int udata = LuaLib.luanet_rawnetobj(luaState, 1);
if(udata != -1)
translator.collectObject(udata);
else
{
// Debug.WriteLine("not found: " + udata);
}
return 0;
}
/*
* __tostring metafunction of CLR objects.
*/
private int toString(LuaCore.lua_State luaState)
{
object obj = translator.getRawNetObject(luaState, 1);
if(!obj.IsNull())
translator.push(luaState, obj.ToString() + ": " + obj.GetHashCode());
else
LuaCore.lua_pushnil(luaState);
return 1;
}
/// <summary>
/// Debug tool to dump the lua stack
/// </summary>
/// FIXME, move somewhere else
public static void dumpStack(ObjectTranslator translator, LuaCore.lua_State luaState)
{
int depth = LuaCore.lua_gettop(luaState);
Debug.WriteLine("lua stack depth: " + depth);
for(int i = 1; i <= depth; i++)
{
var type = LuaCore.lua_type(luaState, i).ToLuaTypes();
// we dump stacks when deep in calls, calling typename while the stack is in flux can fail sometimes, so manually check for key types
string typestr = (type == LuaTypes.Table) ? "table" : LuaCore.lua_typename(luaState, (int)type).ToString();
string strrep = LuaCore.lua_tostring(luaState, i).ToString();
if(type == LuaTypes.UserData)
{
object obj = translator.getRawNetObject(luaState, i);
strrep = obj.ToString();
}
Debug.Print("{0}: ({1}) {2}", i, typestr, strrep);
}
}
/*
* Called by the __index metafunction of CLR objects in case the
* method is not cached or it is a field/property/event.
* Receives the object and the member name as arguments and returns
* either the value of the member or a delegate to call it.
* If the member does not exist returns nil.
*/
private int getMethod(LuaCore.lua_State luaState)
{
object obj = translator.getRawNetObject(luaState, 1);
if(obj.IsNull())
{
translator.throwError(luaState, "trying to index an invalid object reference");
LuaCore.lua_pushnil(luaState);
return 1;
}
object index = translator.getObject(luaState, 2);
var indexType = index.GetType();
string methodName = index as string; // will be null if not a string arg
var objType = obj.GetType();
// Handle the most common case, looking up the method by name.
// CP: This will fail when using indexers and attempting to get a value with the same name as a property of the object,
// ie: xmlelement['item'] <- item is a property of xmlelement
try
{
if(!methodName.IsNull() && isMemberPresent(objType, methodName))
return getMember(luaState, objType, obj, methodName, BindingFlags.Instance | BindingFlags.IgnoreCase);
}
catch
{
}
// Try to access by array if the type is right and index is an int (lua numbers always come across as double)
if(objType.IsArray && index is double)
{
int intIndex = (int)((double)index);
if(objType.UnderlyingSystemType == typeof(float[]))
{
float[] arr = ((float[])obj);
translator.push(luaState, arr[intIndex]);
}
else if(objType.UnderlyingSystemType == typeof(double[]))
{
double[] arr = ((double[])obj);
translator.push(luaState, arr[intIndex]);
}
else if(objType.UnderlyingSystemType == typeof(int[]))
{
int[] arr = ((int[])obj);
translator.push(luaState, arr[intIndex]);
}
else
{
object[] arr = (object[])obj;
translator.push(luaState, arr[intIndex]);
}
}
else
{
// Try to use get_Item to index into this .net object
//MethodInfo getter = objType.GetMethod("get_Item");
var methods = objType.GetMethods();
foreach(var mInfo in methods)
{
if(mInfo.Name == "get_Item")
{
//check if the signature matches the input
if(mInfo.GetParameters().Length == 1)
{
var getter = mInfo;
var actualParms = (!getter.IsNull()) ? getter.GetParameters() : null;
if(actualParms.IsNull() || actualParms.Length != 1)
{
translator.throwError(luaState, "method not found (or no indexer): " + index);
LuaCore.lua_pushnil(luaState);
}
else
{
// Get the index in a form acceptable to the getter
index = translator.getAsType(luaState, 2, actualParms[0].ParameterType);
object[] args = new object[1];
// Just call the indexer - if out of bounds an exception will happen
args[0] = index;
try
{
object result = getter.Invoke(obj, args);
translator.push(luaState, result);
}
catch(TargetInvocationException e)
{
// Provide a more readable description for the common case of key not found
if(e.InnerException is KeyNotFoundException)
translator.throwError(luaState, "key '" + index + "' not found ");
else
translator.throwError(luaState, "exception indexing '" + index + "' " + e.Message);
LuaCore.lua_pushnil(luaState);
}
}
}
}
}
}
LuaCore.lua_pushboolean(luaState, 0);
return 2;
}
/*
* __index metafunction of base classes (the base field of Lua tables).
* Adds a prefix to the method name to call the base version of the method.
*/
private int getBaseMethod(LuaCore.lua_State luaState)
{
object obj = translator.getRawNetObject(luaState, 1);
if(obj.IsNull())
{
translator.throwError(luaState, "trying to index an invalid object reference");
LuaCore.lua_pushnil(luaState);
LuaCore.lua_pushboolean(luaState, 0);
return 2;
}
string methodName = LuaCore.lua_tostring(luaState, 2).ToString();
if(methodName.IsNull())
{
LuaCore.lua_pushnil(luaState);
LuaCore.lua_pushboolean(luaState, 0);
return 2;
}
getMember(luaState, obj.GetType(), obj, "__luaInterface_base_" + methodName, BindingFlags.Instance | BindingFlags.IgnoreCase);
LuaCore.lua_settop(luaState, -2);
if(LuaCore.lua_type(luaState, -1).ToLuaTypes() == LuaTypes.Nil)
{
LuaCore.lua_settop(luaState, -2);
return getMember(luaState, obj.GetType(), obj, methodName, BindingFlags.Instance | BindingFlags.IgnoreCase);
}
LuaCore.lua_pushboolean(luaState, 0);
return 2;
}
/// <summary>
/// Does this method exist as either an instance or static?
/// </summary>
/// <param name="objType"></param>
/// <param name="methodName"></param>
/// <returns></returns>
bool isMemberPresent(IReflect objType, string methodName)
{
object cachedMember = checkMemberCache(memberCache, objType, methodName);
if(!cachedMember.IsNull())
return true;
//CP: Removed NonPublic binding search
var members = objType.GetMember(methodName, BindingFlags.Static | BindingFlags.Instance | BindingFlags.Public | BindingFlags.IgnoreCase/* | BindingFlags.NonPublic*/);
return (members.Length > 0);
}
/*
* Pushes the value of a member or a delegate to call it, depending on the type of
* the member. Works with static or instance members.
* Uses reflection to find members, and stores the reflected MemberInfo object in
* a cache (indexed by the type of the object and the name of the member).
*/
private int getMember(LuaCore.lua_State luaState, IReflect objType, object obj, string methodName, BindingFlags bindingType)
{
bool implicitStatic = false;
MemberInfo member = null;
object cachedMember = checkMemberCache(memberCache, objType, methodName);
//object cachedMember=null;
if(cachedMember is LuaCore.lua_CFunction)
{
translator.pushFunction(luaState, (LuaCore.lua_CFunction)cachedMember);
translator.push(luaState, true);
return 2;
}
else if(!cachedMember.IsNull())
member = (MemberInfo)cachedMember;
else
{
//CP: Removed NonPublic binding search
var members = objType.GetMember(methodName, bindingType | BindingFlags.Public | BindingFlags.IgnoreCase/*| BindingFlags.NonPublic*/);
if(members.Length > 0)
member = members[0];
else
{
// If we can't find any suitable instance members, try to find them as statics - but we only want to allow implicit static
// lookups for fields/properties/events -kevinh
//CP: Removed NonPublic binding search and made case insensitive
members = objType.GetMember(methodName, bindingType | BindingFlags.Static | BindingFlags.Public | BindingFlags.IgnoreCase/*| BindingFlags.NonPublic*/);
if(members.Length > 0)
{
member = members[0];
implicitStatic = true;
}
}
}
if(!member.IsNull())
{
if(member.MemberType == MemberTypes.Field)
{
var field = (FieldInfo)member;
if(cachedMember.IsNull())
setMemberCache(memberCache, objType, methodName, member);
try
{
translator.push(luaState, field.GetValue(obj));
}
catch
{
LuaCore.lua_pushnil(luaState);
}
}
else if(member.MemberType == MemberTypes.Property)
{
var property = (PropertyInfo)member;
if(cachedMember.IsNull())
setMemberCache(memberCache, objType, methodName, member);
try
{
object val = property.GetValue(obj, null);
translator.push(luaState, val);
}
catch(ArgumentException)
{
// If we can't find the getter in our class, recurse up to the base class and see
// if they can help.
if(objType is Type && !(((Type)objType) == typeof(object)))
return getMember(luaState, ((Type)objType).BaseType, obj, methodName, bindingType);
else
LuaCore.lua_pushnil(luaState);
}
catch(TargetInvocationException e) // Convert this exception into a Lua error
{
ThrowError(luaState, e);
LuaCore.lua_pushnil(luaState);
}
}
else if(member.MemberType == MemberTypes.Event)
{
var eventInfo = (EventInfo)member;
if(cachedMember.IsNull())
setMemberCache(memberCache, objType, methodName, member);
translator.push(luaState, new RegisterEventHandler(translator.pendingEvents, obj, eventInfo));
}
else if(!implicitStatic)
{
if(member.MemberType == MemberTypes.NestedType)
{
// kevinh - added support for finding nested types
// cache us
if(cachedMember.IsNull())
setMemberCache(memberCache, objType, methodName, member);
// Find the name of our class
string name = member.Name;
var dectype = member.DeclaringType;
// Build a new long name and try to find the type by name
string longname = dectype.FullName + "+" + name;
var nestedType = translator.FindType(longname);
translator.pushType(luaState, nestedType);
}
else
{
// Member type must be 'method'
var wrapper = new LuaCore.lua_CFunction((new LuaMethodWrapper(translator, objType, methodName, bindingType)).call);
if(cachedMember.IsNull())
setMemberCache(memberCache, objType, methodName, wrapper);
translator.pushFunction(luaState, wrapper);
translator.push(luaState, true);
return 2;
}
}
else
{
// If we reach this point we found a static method, but can't use it in this context because the user passed in an instance
translator.throwError(luaState, "can't pass instance to static method " + methodName);
LuaCore.lua_pushnil(luaState);
}
}
else
{
// kevinh - we want to throw an exception because meerly returning 'nil' in this case
// is not sufficient. valid data members may return nil and therefore there must be some
// way to know the member just doesn't exist.
translator.throwError(luaState, "unknown member name " + methodName);
LuaCore.lua_pushnil(luaState);
}
// push false because we are NOT returning a function (see luaIndexFunction)
translator.push(luaState, false);
return 2;
}
/*
* Checks if a MemberInfo object is cached, returning it or null.
*/
private object checkMemberCache(Hashtable memberCache, IReflect objType, string memberName)
{
var members = (Hashtable)memberCache[objType];
return !members.IsNull() ? members[memberName] : null;
}
/*
* Stores a MemberInfo object in the member cache.
*/
private void setMemberCache(Hashtable memberCache, IReflect objType, string memberName, object member)
{
var members = (Hashtable)memberCache[objType];
if(members.IsNull())
{
members = new Hashtable();
memberCache[objType] = members;
}
members[memberName] = member;
}
/*
* __newindex metafunction of CLR objects. Receives the object,
* the member name and the value to be stored as arguments. Throws
* and error if the assignment is invalid.
*/
private int setFieldOrProperty(LuaCore.lua_State luaState)
{
object target = translator.getRawNetObject(luaState, 1);
if(target.IsNull())
{
translator.throwError(luaState, "trying to index and invalid object reference");
return 0;
}
var type = target.GetType();
// First try to look up the parameter as a property name
string detailMessage;
bool didMember = trySetMember(luaState, type, target, BindingFlags.Instance | BindingFlags.IgnoreCase, out detailMessage);
if(didMember)
return 0; // Must have found the property name
// We didn't find a property name, now see if we can use a [] style this accessor to set array contents
try
{
if(type.IsArray && LuaCore.lua_isnumber(luaState, 2).ToBoolean())
{
int index = (int)LuaCore.lua_tonumber(luaState, 2);
var arr = (Array)target;
object val = translator.getAsType(luaState, 3, arr.GetType().GetElementType());
arr.SetValue(val, index);
}
else
{
// Try to see if we have a this[] accessor
var setter = type.GetMethod("set_Item");
if(!setter.IsNull())
{
var args = setter.GetParameters();
var valueType = args[1].ParameterType;
// The new val ue the user specified
object val = translator.getAsType(luaState, 3, valueType);
var indexType = args[0].ParameterType;
object index = translator.getAsType(luaState, 2, indexType);
object[] methodArgs = new object[2];
// Just call the indexer - if out of bounds an exception will happen
methodArgs[0] = index;
methodArgs[1] = val;
setter.Invoke(target, methodArgs);
}
else
translator.throwError(luaState, detailMessage); // Pass the original message from trySetMember because it is probably best
}
}
catch(SEHException)
{
// If we are seeing a C++ exception - this must actually be for Lua's private use. Let it handle it
throw;
}
catch(Exception e)
{
ThrowError(luaState, e);
}
return 0;
}
/// <summary>
/// Tries to set a named property or field
/// </summary>
/// <param name="luaState"></param>
/// <param name="targetType"></param>
/// <param name="target"></param>
/// <param name="bindingType"></param>
/// <returns>false if unable to find the named member, true for success</returns>
private bool trySetMember(LuaCore.lua_State luaState, IReflect targetType, object target, BindingFlags bindingType, out string detailMessage)
{
detailMessage = null; // No error yet
// If not already a string just return - we don't want to call tostring - which has the side effect of
// changing the lua typecode to string
// Note: We don't use isstring because the standard lua C isstring considers either strings or numbers to
// be true for isstring.
if(LuaCore.lua_type(luaState, 2).ToLuaTypes() != LuaTypes.String)
{
detailMessage = "property names must be strings";
return false;
}
// We only look up property names by string
string fieldName = LuaCore.lua_tostring(luaState, 2).ToString();
if(fieldName.IsNull() || fieldName.Length < 1 || !(char.IsLetter(fieldName[0]) || fieldName[0] == '_'))
{
detailMessage = "invalid property name";
return false;
}
// Find our member via reflection or the cache
var member = (MemberInfo)checkMemberCache(memberCache, targetType, fieldName);
if(member.IsNull())
{
//CP: Removed NonPublic binding search and made case insensitive
var members = targetType.GetMember(fieldName, bindingType | BindingFlags.Public | BindingFlags.IgnoreCase/*| BindingFlags.NonPublic*/);
if(members.Length > 0)
{
member = members[0];
setMemberCache(memberCache, targetType, fieldName, member);
}
else
{
detailMessage = "field or property '" + fieldName + "' does not exist";
return false;
}
}
if(member.MemberType == MemberTypes.Field)
{
var field = (FieldInfo)member;
object val = translator.getAsType(luaState, 3, field.FieldType);
try
{
field.SetValue(target, val);
}
catch (Exception e)
{
ThrowError(luaState, e);
}
// We did a call
return true;
}
else if(member.MemberType == MemberTypes.Property)
{
var property = (PropertyInfo)member;
object val = translator.getAsType(luaState, 3, property.PropertyType);
try
{
property.SetValue(target, val, null);
}
catch (Exception e)
{
ThrowError(luaState, e);
}
// We did a call
return true;
}
detailMessage = "'" + fieldName + "' is not a .net field or property";
return false;
}
/*
* Writes to fields or properties, either static or instance. Throws an error
* if the operation is invalid.
*/
private int setMember(LuaCore.lua_State luaState, IReflect targetType, object target, BindingFlags bindingType)
{
string detail;
bool success = trySetMember(luaState, targetType, target, bindingType, out detail);
if(!success)
translator.throwError(luaState, detail);
return 0;
}
/// <summary>
/// Convert a C# exception into a Lua error
/// </summary>
/// <param name="e"></param>
/// We try to look into the exception to give the most meaningful description
void ThrowError(LuaCore.lua_State luaState, Exception e)
{
// If we got inside a reflection show what really happened
var te = e as TargetInvocationException;
if (!te.IsNull())
e = te.InnerException;
translator.throwError(luaState, e);
}
/*
* __index metafunction of type references, works on static members.
*/
private int getClassMethod(LuaCore.lua_State luaState)
{
IReflect klass;
object obj = translator.getRawNetObject(luaState, 1);
if(obj.IsNull() || !(obj is IReflect))
{
translator.throwError(luaState, "trying to index an invalid type reference");
LuaCore.lua_pushnil(luaState);
return 1;
}
else
klass = (IReflect)obj;
if(LuaCore.lua_isnumber(luaState, 2).ToBoolean())
{
int size = (int)LuaCore.lua_tonumber(luaState, 2);
translator.push(luaState, Array.CreateInstance(klass.UnderlyingSystemType, size));
return 1;
}
else
{
string methodName = LuaCore.lua_tostring(luaState, 2).ToString();
if(methodName.IsNull())
{
LuaCore.lua_pushnil(luaState);
return 1;
} //CP: Ignore case
else
return getMember(luaState, klass, null, methodName, BindingFlags.FlattenHierarchy | BindingFlags.Static | BindingFlags.IgnoreCase);
}
}
/*
* __newindex function of type references, works on static members.
*/
private int setClassFieldOrProperty(LuaCore.lua_State luaState)
{
IReflect target;
object obj = translator.getRawNetObject(luaState, 1);
if(obj.IsNull() || !(obj is IReflect))
{
translator.throwError(luaState, "trying to index an invalid type reference");
return 0;
}
else
target = (IReflect)obj;
return setMember(luaState, target, null, BindingFlags.FlattenHierarchy | BindingFlags.Static | BindingFlags.IgnoreCase);
}
/*
* __call metafunction of type references. Searches for and calls
* a constructor for the type. Returns nil if the constructor is not
* found or if the arguments are invalid. Throws an error if the constructor
* generates an exception.
*/
private int callConstructor(LuaCore.lua_State luaState)
{
var validConstructor = new MethodCache();
IReflect klass;
object obj = translator.getRawNetObject(luaState, 1);
if(obj.IsNull() || !(obj is IReflect))
{
translator.throwError(luaState, "trying to call constructor on an invalid type reference");
LuaCore.lua_pushnil(luaState);
return 1;
}
else
klass = (IReflect)obj;
LuaCore.lua_remove(luaState, 1);
var constructors = klass.UnderlyingSystemType.GetConstructors();
foreach(var constructor in constructors)
{
bool isConstructor = matchParameters(luaState, constructor, ref validConstructor);
if(isConstructor)
{
try
{
translator.push(luaState, constructor.Invoke(validConstructor.args));
}
catch(TargetInvocationException e)
{
ThrowError(luaState, e);
LuaCore.lua_pushnil(luaState);
}
catch
{
LuaCore.lua_pushnil(luaState);
}
return 1;
}
}
string constructorName = (constructors.Length == 0) ? "unknown" : constructors[0].Name;
translator.throwError(luaState, String.Format("{0} does not contain constructor({1}) argument match",
klass.UnderlyingSystemType, constructorName));
LuaCore.lua_pushnil(luaState);
return 1;
}
/*
* Matches a method against its arguments in the Lua stack. Returns
* if the match was succesful. It it was also returns the information
* necessary to invoke the method.
*/
internal bool matchParameters(LuaCore.lua_State luaState, MethodBase method, ref MethodCache methodCache)
{
ExtractValue extractValue;
bool isMethod = true;
var paramInfo = method.GetParameters();
int currentLuaParam = 1;
int nLuaParams = LuaCore.lua_gettop(luaState);
var paramList = new ArrayList();
var outList = new List<int>();
var argTypes = new List<MethodArgs>();
foreach(var currentNetParam in paramInfo)
{
if(!currentNetParam.IsIn && currentNetParam.IsOut) // Skips out params
outList.Add(paramList.Add(null));
else if(currentLuaParam > nLuaParams) // Adds optional parameters
{
if(currentNetParam.IsOptional)
paramList.Add(currentNetParam.DefaultValue);
else
{
isMethod = false;
break;
}
}
else if(_IsTypeCorrect(luaState, currentLuaParam, currentNetParam, out extractValue)) // Type checking
{
int index = paramList.Add(extractValue(luaState, currentLuaParam));
var methodArg = new MethodArgs();
methodArg.index = index;
methodArg.extractValue = extractValue;
argTypes.Add(methodArg);
if(currentNetParam.ParameterType.IsByRef)
outList.Add(index);
currentLuaParam++;
} // Type does not match, ignore if the parameter is optional
else if(_IsParamsArray(luaState, currentLuaParam, currentNetParam, out extractValue))
{
object luaParamValue = extractValue(luaState, currentLuaParam);
var paramArrayType = currentNetParam.ParameterType.GetElementType();
Array paramArray;
if(luaParamValue is LuaTable)
{
var table = (LuaTable)luaParamValue;
var tableEnumerator = table.GetEnumerator();
paramArray = Array.CreateInstance(paramArrayType, table.Values.Count);
tableEnumerator.Reset();
int paramArrayIndex = 0;
while(tableEnumerator.MoveNext())
{
paramArray.SetValue(Convert.ChangeType(tableEnumerator.Value, currentNetParam.ParameterType.GetElementType()), paramArrayIndex);
paramArrayIndex++;
}
}
else
{
paramArray = Array.CreateInstance(paramArrayType, 1);
paramArray.SetValue(luaParamValue, 0);
}
int index = paramList.Add(paramArray);
var methodArg = new MethodArgs();
methodArg.index = index;
methodArg.extractValue = extractValue;
methodArg.isParamsArray = true;
methodArg.paramsArrayType = paramArrayType;
argTypes.Add(methodArg);
currentLuaParam++;
}
else if(currentNetParam.IsOptional)
paramList.Add(currentNetParam.DefaultValue);
else // No match
{
isMethod = false;
break;
}
}
if(currentLuaParam != nLuaParams + 1) // Number of parameters does not match
isMethod = false;
if(isMethod)
{
methodCache.args = paramList.ToArray();
methodCache.cachedMethod = method;
methodCache.outList = outList.ToArray();
methodCache.argTypes = argTypes.ToArray();
}
return isMethod;
}
/// <summary>
/// CP: Fix for operator overloading failure
/// Returns true if the type is set and assigns the extract value
/// </summary>
/// <param name="luaState"></param>
/// <param name="currentLuaParam"></param>
/// <param name="currentNetParam"></param>
/// <param name="extractValue"></param>
/// <returns></returns>
private bool _IsTypeCorrect(LuaCore.lua_State luaState, int currentLuaParam, ParameterInfo currentNetParam, out ExtractValue extractValue)
{
try
{
return (extractValue = translator.typeChecker.checkType(luaState, currentLuaParam, currentNetParam.ParameterType)) != null;
}
catch
{
extractValue = null;
Debug.WriteLine("Type wasn't correct");
return false;
}
}
private bool _IsParamsArray(LuaCore.lua_State luaState, int currentLuaParam, ParameterInfo currentNetParam, out ExtractValue extractValue)
{
extractValue = null;
if (currentNetParam.GetCustomAttributes(typeof(ParamArrayAttribute), false).Length > 0)
{
LuaTypes luaType;
try
{
luaType = LuaCore.lua_type(luaState, currentLuaParam).ToLuaTypes();
}
catch(Exception ex)
{
Debug.WriteLine("Could not retrieve lua type while attempting to determine params Array Status.");
Debug.WriteLine(ex.Message);
extractValue = null;
return false;
}
if(luaType == LuaTypes.Table)
{
try
{
extractValue = translator.typeChecker.getExtractor(typeof(LuaTable));
}
catch(Exception/* ex*/)
{
Debug.WriteLine("An error occurred during an attempt to retrieve a LuaTable extractor while checking for params array status.");
}
if(!extractValue.IsNull())
{
return true;
}
}
else
{
var paramElementType = currentNetParam.ParameterType.GetElementType();
try
{
extractValue = translator.typeChecker.checkType(luaState, currentLuaParam, paramElementType);
}
catch (Exception/* ex*/)
{
Debug.WriteLine(string.Format("An error occurred during an attempt to retrieve an extractor ({0}) while checking for params array status.", paramElementType.FullName));
}
if(!extractValue.IsNull())
{
return true;
}
}
}
Debug.WriteLine("Type wasn't Params object.");
return false;
}
}
}
\ No newline at end of file
/*
* This file is part of LuaInterface.
*
* Copyright (C) 2003-2005 Fabio Mascarenhas de Queiroz.
* Copyright (C) 2012 Megax <http://megax.yeahunter.hu/>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
using System;
using System.Diagnostics;
using System.Collections.Generic;
namespace LuaInterface.Method
{
/// <summary>
/// We keep track of what delegates we have auto attached to an event - to allow us to cleanly exit a LuaInterface session
/// </summary>
class EventHandlerContainer : IDisposable
{
private Dictionary<Delegate, RegisterEventHandler> dict = new Dictionary<Delegate, RegisterEventHandler>();
public void Add(Delegate handler, RegisterEventHandler eventInfo)
{
dict.Add(handler, eventInfo);
}
public void Remove(Delegate handler)
{
bool found = dict.Remove(handler);
Debug.Assert(found);
}
/// <summary>
/// Remove any still registered handlers
/// </summary>
public void Dispose()
{
foreach(KeyValuePair<Delegate, RegisterEventHandler> pair in dict)
pair.Value.RemovePending(pair.Key);
dict.Clear();
}
}
/*
* This file is part of LuaInterface.
*
* Copyright (C) 2003-2005 Fabio Mascarenhas de Queiroz.
* Copyright (C) 2012 Megax <http://megax.yeahunter.hu/>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
using System;
using System.Diagnostics;
using System.Collections.Generic;
namespace LuaInterface.Method
{
/// <summary>
/// We keep track of what delegates we have auto attached to an event - to allow us to cleanly exit a LuaInterface session
/// </summary>
class EventHandlerContainer : IDisposable
{
private Dictionary<Delegate, RegisterEventHandler> dict = new Dictionary<Delegate, RegisterEventHandler>();
public void Add(Delegate handler, RegisterEventHandler eventInfo)
{
dict.Add(handler, eventInfo);
}
public void Remove(Delegate handler)
{
bool found = dict.Remove(handler);
Debug.Assert(found);
}
/// <summary>
/// Remove any still registered handlers
/// </summary>
public void Dispose()
{
foreach(KeyValuePair<Delegate, RegisterEventHandler> pair in dict)
pair.Value.RemovePending(pair.Key);
dict.Clear();
}
}
}
\ No newline at end of file
/*
* This file is part of LuaInterface.
*
* Copyright (C) 2003-2005 Fabio Mascarenhas de Queiroz.
* Copyright (C) 2012 Megax <http://megax.yeahunter.hu/>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
using System;
namespace LuaInterface.Method
{
/*
* Static helper methods for Lua tables acting as CLR objects.
*
* Author: Fabio Mascarenhas
* Version: 1.0
*/
public class LuaClassHelper
{
/*
* Gets the function called name from the provided table,
* returning null if it does not exist
*/
public static LuaFunction getTableFunction(LuaTable luaTable, string name)
{
object funcObj = luaTable.rawget(name);
if(funcObj is LuaFunction)
return (LuaFunction)funcObj;
else
return null;
}
/*
* Calls the provided function with the provided parameters
*/
public static object callFunction(LuaFunction function, object[] args, Type[] returnTypes, object[] inArgs, int[] outArgs)
{
// args is the return array of arguments, inArgs is the actual array
// of arguments passed to the function (with in parameters only), outArgs
// has the positions of out parameters
object returnValue;
int iRefArgs;
object[] returnValues = function.call(inArgs, returnTypes);
if(returnTypes[0] == typeof(void))
{
returnValue = null;
iRefArgs = 0;
}
else
{
returnValue = returnValues[0];
iRefArgs = 1;
}
for(int i = 0; i < outArgs.Length; i++)
{
args[outArgs[i]] = returnValues[iRefArgs];
iRefArgs++;
}
return returnValue;
}
}
/*
* This file is part of LuaInterface.
*
* Copyright (C) 2003-2005 Fabio Mascarenhas de Queiroz.
* Copyright (C) 2012 Megax <http://megax.yeahunter.hu/>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
using System;
namespace LuaInterface.Method
{
/*
* Static helper methods for Lua tables acting as CLR objects.
*
* Author: Fabio Mascarenhas
* Version: 1.0
*/
public class LuaClassHelper
{
/*
* Gets the function called name from the provided table,
* returning null if it does not exist
*/
public static LuaFunction getTableFunction(LuaTable luaTable, string name)
{
object funcObj = luaTable.rawget(name);
if(funcObj is LuaFunction)
return (LuaFunction)funcObj;
else
return null;
}
/*
* Calls the provided function with the provided parameters
*/
public static object callFunction(LuaFunction function, object[] args, Type[] returnTypes, object[] inArgs, int[] outArgs)
{
// args is the return array of arguments, inArgs is the actual array
// of arguments passed to the function (with in parameters only), outArgs
// has the positions of out parameters
object returnValue;
int iRefArgs;
object[] returnValues = function.call(inArgs, returnTypes);
if(returnTypes[0] == typeof(void))
{
returnValue = null;
iRefArgs = 0;
}
else
{
returnValue = returnValues[0];
iRefArgs = 1;
}
for(int i = 0; i < outArgs.Length; i++)
{
args[outArgs[i]] = returnValues[iRefArgs];
iRefArgs++;
}
return returnValue;
}
}
}
\ No newline at end of file
/*
* This file is part of LuaInterface.
*
* Copyright (C) 2003-2005 Fabio Mascarenhas de Queiroz.
* Copyright (C) 2012 Megax <http://megax.yeahunter.hu/>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
using System;
namespace LuaInterface.Method
{
/*
* Wrapper class for Lua functions as delegates
* Subclasses with correct signatures are created
* at runtime.
*
* Author: Fabio Mascarenhas
* Version: 1.0
*/
public class LuaDelegate
{
public LuaFunction function;
public Type[] returnTypes;
public LuaDelegate()
{
function = null;
returnTypes = null;
}
public object callFunction(object[] args, object[] inArgs, int[] outArgs)
{
// args is the return array of arguments, inArgs is the actual array
// of arguments passed to the function (with in parameters only), outArgs
// has the positions of out parameters
object returnValue;
int iRefArgs;
object[] returnValues = function.call(inArgs, returnTypes);
if(returnTypes[0] == typeof(void))
{
returnValue = null;
iRefArgs = 0;
}
else
{
returnValue = returnValues[0];
iRefArgs = 1;
}
// Sets the value of out and ref parameters (from
// the values returned by the Lua function).
for(int i = 0; i < outArgs.Length; i++)
{
args[outArgs[i]] = returnValues[iRefArgs];
iRefArgs++;
}
return returnValue;
}
}
/*
* This file is part of LuaInterface.
*
* Copyright (C) 2003-2005 Fabio Mascarenhas de Queiroz.
* Copyright (C) 2012 Megax <http://megax.yeahunter.hu/>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
using System;
namespace LuaInterface.Method
{
/*
* Wrapper class for Lua functions as delegates
* Subclasses with correct signatures are created
* at runtime.
*
* Author: Fabio Mascarenhas
* Version: 1.0
*/
public class LuaDelegate
{
public LuaFunction function;
public Type[] returnTypes;
public LuaDelegate()
{
function = null;
returnTypes = null;
}
public object callFunction(object[] args, object[] inArgs, int[] outArgs)
{
// args is the return array of arguments, inArgs is the actual array
// of arguments passed to the function (with in parameters only), outArgs
// has the positions of out parameters
object returnValue;
int iRefArgs;
object[] returnValues = function.call(inArgs, returnTypes);
if(returnTypes[0] == typeof(void))
{
returnValue = null;
iRefArgs = 0;
}
else
{
returnValue = returnValues[0];
iRefArgs = 1;
}
// Sets the value of out and ref parameters (from
// the values returned by the Lua function).
for(int i = 0; i < outArgs.Length; i++)
{
args[outArgs[i]] = returnValues[iRefArgs];
iRefArgs++;
}
return returnValue;
}
}
}
\ No newline at end of file
/*
* This file is part of LuaInterface.
*
* Copyright (C) 2003-2005 Fabio Mascarenhas de Queiroz.
* Copyright (C) 2012 Megax <http://megax.yeahunter.hu/>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
using System;
namespace LuaInterface.Method
{
/*
* Base wrapper class for Lua function event handlers.
* Subclasses that do actual event handling are created
* at runtime.
*
* Author: Fabio Mascarenhas
* Version: 1.0
*/
public class LuaEventHandler
{
public LuaFunction handler = null;
// CP: Fix provided by Ben Bryant for delegates with one param
// link: http://luaforge.net/forum/message.php?msg_id=9318
public void handleEvent(object[] args)
{
handler.Call(args);
}
//public void handleEvent(object sender,object data)
//{
// handler.call(new object[] { sender,data },new Type[0]);
//}
}
/*
* This file is part of LuaInterface.
*
* Copyright (C) 2003-2005 Fabio Mascarenhas de Queiroz.
* Copyright (C) 2012 Megax <http://megax.yeahunter.hu/>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
using System;
namespace LuaInterface.Method
{
/*
* Base wrapper class for Lua function event handlers.
* Subclasses that do actual event handling are created
* at runtime.
*
* Author: Fabio Mascarenhas
* Version: 1.0
*/
public class LuaEventHandler
{
public LuaFunction handler = null;
// CP: Fix provided by Ben Bryant for delegates with one param
// link: http://luaforge.net/forum/message.php?msg_id=9318
public void handleEvent(object[] args)
{
handler.Call(args);
}
//public void handleEvent(object sender,object data)
//{
// handler.call(new object[] { sender,data },new Type[0]);
//}
}
}
\ No newline at end of file
/*
* This file is part of LuaInterface.
*
* Copyright (C) 2003-2005 Fabio Mascarenhas de Queiroz.
* Copyright (C) 2012 Megax <http://megax.yeahunter.hu/>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
using System;
using System.Reflection;
using System.Collections.Generic;
using LuaInterface.Exceptions;
using LuaInterface.Extensions;
namespace LuaInterface.Method
{
using LuaCore = KopiLua.Lua;
/*
* Argument extraction with type-conversion function
*/
delegate object ExtractValue(LuaCore.lua_State luaState, int stackPos);
/*
* Wrapper class for methods/constructors accessed from Lua.
*
* Author: Fabio Mascarenhas
* Version: 1.0
*/
class LuaMethodWrapper
{
private ObjectTranslator _Translator;
private MethodBase _Method;
private MethodCache _LastCalledMethod = new MethodCache();
private string _MethodName;
private MemberInfo[] _Members;
private IReflect _TargetType;
private ExtractValue _ExtractTarget;
private object _Target;
private BindingFlags _BindingType;
/*
* Constructs the wrapper for a known MethodBase instance
*/
public LuaMethodWrapper(ObjectTranslator translator, object target, IReflect targetType, MethodBase method)
{
_Translator = translator;
_Target = target;
_TargetType = targetType;
if(!targetType.IsNull())
_ExtractTarget = translator.typeChecker.getExtractor(targetType);
_Method = method;
_MethodName = method.Name;
if(method.IsStatic)
_BindingType = BindingFlags.Static;
else
_BindingType = BindingFlags.Instance;
}
/*
* Constructs the wrapper for a known method name
*/
public LuaMethodWrapper(ObjectTranslator translator, IReflect targetType, string methodName, BindingFlags bindingType)
{
_Translator = translator;
_MethodName = methodName;
_TargetType = targetType;
if(!targetType.IsNull())
_ExtractTarget = translator.typeChecker.getExtractor(targetType);
_BindingType = bindingType;
//CP: Removed NonPublic binding search and added IgnoreCase
_Members = targetType.UnderlyingSystemType.GetMember(methodName, MemberTypes.Method, bindingType | BindingFlags.Public | BindingFlags.IgnoreCase/*|BindingFlags.NonPublic*/);
}
/// <summary>
/// Convert C# exceptions into Lua errors
/// </summary>
/// <returns>num of things on stack</returns>
/// <param name="e">null for no pending exception</param>
int SetPendingException(Exception e)
{
return _Translator.interpreter.SetPendingException(e);
}
/*
* Calls the method. Receives the arguments from the Lua stack
* and returns values in it.
*/
public int call(LuaCore.lua_State luaState)
{
var methodToCall = _Method;
object targetObject = _Target;
bool failedCall = true;
int nReturnValues = 0;
if(!LuaCore.lua_checkstack(luaState, 5).ToBoolean())
throw new LuaException("Lua stack overflow");
bool isStatic = (_BindingType & BindingFlags.Static) == BindingFlags.Static;
SetPendingException(null);
if(methodToCall.IsNull()) // Method from name
{
if(isStatic)
targetObject = null;
else
targetObject = _ExtractTarget(luaState, 1);
//LuaCore.lua_remove(luaState,1); // Pops the receiver
if(!_LastCalledMethod.cachedMethod.IsNull()) // Cached?
{
int numStackToSkip = isStatic ? 0 : 1; // If this is an instance invoe we will have an extra arg on the stack for the targetObject
int numArgsPassed = LuaCore.lua_gettop(luaState) - numStackToSkip;
if(numArgsPassed == _LastCalledMethod.argTypes.Length) // No. of args match?
{
if(!LuaCore.lua_checkstack(luaState, _LastCalledMethod.outList.Length + 6).ToBoolean())
throw new LuaException("Lua stack overflow");
try
{
for(int i = 0; i < _LastCalledMethod.argTypes.Length; i++)
{
if(_LastCalledMethod.argTypes[i].isParamsArray)
{
object luaParamValue = _LastCalledMethod.argTypes[i].extractValue(luaState, i + 1 + numStackToSkip);
var paramArrayType = _LastCalledMethod.argTypes[i].paramsArrayType;
Array paramArray;
if(luaParamValue is LuaTable)
{
var table = (LuaTable)luaParamValue;
paramArray = Array.CreateInstance(paramArrayType, table.Values.Count);
for(int x = 1; x <= table.Values.Count; x++)
paramArray.SetValue(Convert.ChangeType(table[x], paramArrayType), x - 1);
}
else
{
paramArray = Array.CreateInstance(paramArrayType, 1);
paramArray.SetValue(luaParamValue, 0);
}
_LastCalledMethod.args[_LastCalledMethod.argTypes[i].index] = paramArray;
}
else
{
_LastCalledMethod.args[_LastCalledMethod.argTypes[i].index] =
_LastCalledMethod.argTypes[i].extractValue(luaState, i + 1 + numStackToSkip);
}
if(_LastCalledMethod.args[_LastCalledMethod.argTypes[i].index] == null &&
!LuaCore.lua_isnil(luaState, i + 1 + numStackToSkip))
throw new LuaException("argument number " + (i + 1) + " is invalid");
}
if((_BindingType & BindingFlags.Static) == BindingFlags.Static)
_Translator.push(luaState, _LastCalledMethod.cachedMethod.Invoke(null, _LastCalledMethod.args));
else
{
if(_LastCalledMethod.cachedMethod.IsConstructor)
_Translator.push(luaState, ((ConstructorInfo)_LastCalledMethod.cachedMethod).Invoke(_LastCalledMethod.args));
else
_Translator.push(luaState, _LastCalledMethod.cachedMethod.Invoke(targetObject, _LastCalledMethod.args));
}
failedCall = false;
}
catch(TargetInvocationException e)
{
// Failure of method invocation
return SetPendingException(e.GetBaseException());
}
catch(Exception e)
{
if(_Members.Length == 1) // Is the method overloaded?
// No, throw error
return SetPendingException(e);
}
}
}
// Cache miss
if(failedCall)
{
// System.Diagnostics.Debug.WriteLine("cache miss on " + methodName);
// If we are running an instance variable, we can now pop the targetObject from the stack
if(!isStatic)
{
if(targetObject.IsNull())
{
_Translator.throwError(luaState, String.Format("instance method '{0}' requires a non null target object", _MethodName));
LuaCore.lua_pushnil(luaState);
return 1;
}
LuaCore.lua_remove(luaState, 1); // Pops the receiver
}
bool hasMatch = false;
string candidateName = null;
foreach(var member in _Members)
{
candidateName = member.ReflectedType.Name + "." + member.Name;
var m = (MethodInfo)member;
bool isMethod = _Translator.matchParameters(luaState, m, ref _LastCalledMethod);
if(isMethod)
{
hasMatch = true;
break;
}
}
if(!hasMatch)
{
string msg = (candidateName == null) ? "invalid arguments to method call" : ("invalid arguments to method: " + candidateName);
_Translator.throwError(luaState, msg);
LuaCore.lua_pushnil(luaState);
return 1;
}
}
}
else // Method from MethodBase instance
{
if(methodToCall.ContainsGenericParameters)
{
bool isMethod = _Translator.matchParameters(luaState, methodToCall, ref _LastCalledMethod);
if(methodToCall.IsGenericMethodDefinition)
{
//need to make a concrete type of the generic method definition
var typeArgs = new List<Type>();
foreach(object arg in _LastCalledMethod.args)
typeArgs.Add(arg.GetType());
var concreteMethod = (methodToCall as MethodInfo).MakeGenericMethod(typeArgs.ToArray());
_Translator.push(luaState, concreteMethod.Invoke(targetObject, _LastCalledMethod.args));
failedCall = false;
}
else if(methodToCall.ContainsGenericParameters)
{
_Translator.throwError(luaState, "unable to invoke method on generic class as the current method is an open generic method");
LuaCore.lua_pushnil(luaState);
return 1;
}
}
else
{
if(!methodToCall.IsStatic && !methodToCall.IsConstructor && targetObject == null)
{
targetObject = _ExtractTarget(luaState, 1);
LuaCore.lua_remove(luaState, 1); // Pops the receiver
}
if(!_Translator.matchParameters(luaState, methodToCall, ref _LastCalledMethod))
{
_Translator.throwError(luaState, "invalid arguments to method call");
LuaCore.lua_pushnil(luaState);
return 1;
}
}
}
if(failedCall)
{
if(!LuaCore.lua_checkstack(luaState, _LastCalledMethod.outList.Length + 6).ToBoolean())
throw new LuaException("Lua stack overflow");
try
{
if(isStatic)
_Translator.push(luaState, _LastCalledMethod.cachedMethod.Invoke(null, _LastCalledMethod.args));
else
{
if(_LastCalledMethod.cachedMethod.IsConstructor)
_Translator.push(luaState, ((ConstructorInfo)_LastCalledMethod.cachedMethod).Invoke(_LastCalledMethod.args));
else
_Translator.push(luaState, _LastCalledMethod.cachedMethod.Invoke(targetObject, _LastCalledMethod.args));
}
}
catch(TargetInvocationException e)
{
return SetPendingException(e.GetBaseException());
}
catch(Exception e)
{
return SetPendingException(e);
}
}
// Pushes out and ref return values
for(int index = 0; index < _LastCalledMethod.outList.Length; index++)
{
nReturnValues++;
//for(int i=0;i<lastCalledMethod.outList.Length;i++)
_Translator.push(luaState, _LastCalledMethod.args[_LastCalledMethod.outList[index]]);
}
//by isSingle 2010-09-10 11:26:31
//Desc:
// if not return void,we need add 1,
// or we will lost the function's return value
// when call dotnet function like "int foo(arg1,out arg2,out arg3)" in lua code
if(!_LastCalledMethod.IsReturnVoid && nReturnValues > 0)
nReturnValues++;
return nReturnValues < 1 ? 1 : nReturnValues;
}
}
/*
* This file is part of LuaInterface.
*
* Copyright (C) 2003-2005 Fabio Mascarenhas de Queiroz.
* Copyright (C) 2012 Megax <http://megax.yeahunter.hu/>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
using System;
using System.Reflection;
using System.Collections.Generic;
using LuaInterface.Exceptions;
using LuaInterface.Extensions;
namespace LuaInterface.Method
{
using LuaCore = KopiLua.Lua;
/*
* Argument extraction with type-conversion function
*/
delegate object ExtractValue(LuaCore.lua_State luaState, int stackPos);
/*
* Wrapper class for methods/constructors accessed from Lua.
*
* Author: Fabio Mascarenhas
* Version: 1.0
*/
class LuaMethodWrapper
{
private ObjectTranslator _Translator;
private MethodBase _Method;
private MethodCache _LastCalledMethod = new MethodCache();
private string _MethodName;
private MemberInfo[] _Members;
private IReflect _TargetType;
private ExtractValue _ExtractTarget;
private object _Target;
private BindingFlags _BindingType;
/*
* Constructs the wrapper for a known MethodBase instance
*/
public LuaMethodWrapper(ObjectTranslator translator, object target, IReflect targetType, MethodBase method)
{
_Translator = translator;
_Target = target;
_TargetType = targetType;
if(!targetType.IsNull())
_ExtractTarget = translator.typeChecker.getExtractor(targetType);
_Method = method;
_MethodName = method.Name;
if(method.IsStatic)
_BindingType = BindingFlags.Static;
else
_BindingType = BindingFlags.Instance;
}
/*
* Constructs the wrapper for a known method name
*/
public LuaMethodWrapper(ObjectTranslator translator, IReflect targetType, string methodName, BindingFlags bindingType)
{
_Translator = translator;
_MethodName = methodName;
_TargetType = targetType;
if(!targetType.IsNull())
_ExtractTarget = translator.typeChecker.getExtractor(targetType);
_BindingType = bindingType;
//CP: Removed NonPublic binding search and added IgnoreCase
_Members = targetType.UnderlyingSystemType.GetMember(methodName, MemberTypes.Method, bindingType | BindingFlags.Public | BindingFlags.IgnoreCase/*|BindingFlags.NonPublic*/);
}
/// <summary>
/// Convert C# exceptions into Lua errors
/// </summary>
/// <returns>num of things on stack</returns>
/// <param name="e">null for no pending exception</param>
int SetPendingException(Exception e)
{
return _Translator.interpreter.SetPendingException(e);
}
/*
* Calls the method. Receives the arguments from the Lua stack
* and returns values in it.
*/
public int call(LuaCore.lua_State luaState)
{
var methodToCall = _Method;
object targetObject = _Target;
bool failedCall = true;
int nReturnValues = 0;
if(!LuaCore.lua_checkstack(luaState, 5).ToBoolean())
throw new LuaException("Lua stack overflow");
bool isStatic = (_BindingType & BindingFlags.Static) == BindingFlags.Static;
SetPendingException(null);
if(methodToCall.IsNull()) // Method from name
{
if(isStatic)
targetObject = null;
else
targetObject = _ExtractTarget(luaState, 1);
//LuaCore.lua_remove(luaState,1); // Pops the receiver
if(!_LastCalledMethod.cachedMethod.IsNull()) // Cached?
{
int numStackToSkip = isStatic ? 0 : 1; // If this is an instance invoe we will have an extra arg on the stack for the targetObject
int numArgsPassed = LuaCore.lua_gettop(luaState) - numStackToSkip;
if(numArgsPassed == _LastCalledMethod.argTypes.Length) // No. of args match?
{
if(!LuaCore.lua_checkstack(luaState, _LastCalledMethod.outList.Length + 6).ToBoolean())
throw new LuaException("Lua stack overflow");
try
{
for(int i = 0; i < _LastCalledMethod.argTypes.Length; i++)
{
if(_LastCalledMethod.argTypes[i].isParamsArray)
{
object luaParamValue = _LastCalledMethod.argTypes[i].extractValue(luaState, i + 1 + numStackToSkip);
var paramArrayType = _LastCalledMethod.argTypes[i].paramsArrayType;
Array paramArray;
if(luaParamValue is LuaTable)
{
var table = (LuaTable)luaParamValue;
paramArray = Array.CreateInstance(paramArrayType, table.Values.Count);
for(int x = 1; x <= table.Values.Count; x++)
paramArray.SetValue(Convert.ChangeType(table[x], paramArrayType), x - 1);
}
else
{
paramArray = Array.CreateInstance(paramArrayType, 1);
paramArray.SetValue(luaParamValue, 0);
}
_LastCalledMethod.args[_LastCalledMethod.argTypes[i].index] = paramArray;
}
else
{
_LastCalledMethod.args[_LastCalledMethod.argTypes[i].index] =
_LastCalledMethod.argTypes[i].extractValue(luaState, i + 1 + numStackToSkip);
}
if(_LastCalledMethod.args[_LastCalledMethod.argTypes[i].index] == null &&
!LuaCore.lua_isnil(luaState, i + 1 + numStackToSkip))
throw new LuaException("argument number " + (i + 1) + " is invalid");
}
if((_BindingType & BindingFlags.Static) == BindingFlags.Static)
_Translator.push(luaState, _LastCalledMethod.cachedMethod.Invoke(null, _LastCalledMethod.args));
else
{
if(_LastCalledMethod.cachedMethod.IsConstructor)
_Translator.push(luaState, ((ConstructorInfo)_LastCalledMethod.cachedMethod).Invoke(_LastCalledMethod.args));
else
_Translator.push(luaState, _LastCalledMethod.cachedMethod.Invoke(targetObject, _LastCalledMethod.args));
}
failedCall = false;
}
catch(TargetInvocationException e)
{
// Failure of method invocation
return SetPendingException(e.GetBaseException());
}
catch(Exception e)
{
if(_Members.Length == 1) // Is the method overloaded?
// No, throw error
return SetPendingException(e);
}
}
}
// Cache miss
if(failedCall)
{
// System.Diagnostics.Debug.WriteLine("cache miss on " + methodName);
// If we are running an instance variable, we can now pop the targetObject from the stack
if(!isStatic)
{
if(targetObject.IsNull())
{
_Translator.throwError(luaState, String.Format("instance method '{0}' requires a non null target object", _MethodName));
LuaCore.lua_pushnil(luaState);
return 1;
}
LuaCore.lua_remove(luaState, 1); // Pops the receiver
}
bool hasMatch = false;
string candidateName = null;
foreach(var member in _Members)
{
candidateName = member.ReflectedType.Name + "." + member.Name;
var m = (MethodInfo)member;
bool isMethod = _Translator.matchParameters(luaState, m, ref _LastCalledMethod);
if(isMethod)
{
hasMatch = true;
break;
}
}
if(!hasMatch)
{
string msg = (candidateName == null) ? "invalid arguments to method call" : ("invalid arguments to method: " + candidateName);
_Translator.throwError(luaState, msg);
LuaCore.lua_pushnil(luaState);
return 1;
}
}
}
else // Method from MethodBase instance
{
if(methodToCall.ContainsGenericParameters)
{
bool isMethod = _Translator.matchParameters(luaState, methodToCall, ref _LastCalledMethod);
if(methodToCall.IsGenericMethodDefinition)
{
//need to make a concrete type of the generic method definition
var typeArgs = new List<Type>();
foreach(object arg in _LastCalledMethod.args)
typeArgs.Add(arg.GetType());
var concreteMethod = (methodToCall as MethodInfo).MakeGenericMethod(typeArgs.ToArray());
_Translator.push(luaState, concreteMethod.Invoke(targetObject, _LastCalledMethod.args));
failedCall = false;
}
else if(methodToCall.ContainsGenericParameters)
{
_Translator.throwError(luaState, "unable to invoke method on generic class as the current method is an open generic method");
LuaCore.lua_pushnil(luaState);
return 1;
}
}
else
{
if(!methodToCall.IsStatic && !methodToCall.IsConstructor && targetObject == null)
{
targetObject = _ExtractTarget(luaState, 1);
LuaCore.lua_remove(luaState, 1); // Pops the receiver
}
if(!_Translator.matchParameters(luaState, methodToCall, ref _LastCalledMethod))
{
_Translator.throwError(luaState, "invalid arguments to method call");
LuaCore.lua_pushnil(luaState);
return 1;
}
}
}
if(failedCall)
{
if(!LuaCore.lua_checkstack(luaState, _LastCalledMethod.outList.Length + 6).ToBoolean())
throw new LuaException("Lua stack overflow");
try
{
if(isStatic)
_Translator.push(luaState, _LastCalledMethod.cachedMethod.Invoke(null, _LastCalledMethod.args));
else
{
if(_LastCalledMethod.cachedMethod.IsConstructor)
_Translator.push(luaState, ((ConstructorInfo)_LastCalledMethod.cachedMethod).Invoke(_LastCalledMethod.args));
else
_Translator.push(luaState, _LastCalledMethod.cachedMethod.Invoke(targetObject, _LastCalledMethod.args));
}
}
catch(TargetInvocationException e)
{
return SetPendingException(e.GetBaseException());
}
catch(Exception e)
{
return SetPendingException(e);
}
}
// Pushes out and ref return values
for(int index = 0; index < _LastCalledMethod.outList.Length; index++)
{
nReturnValues++;
//for(int i=0;i<lastCalledMethod.outList.Length;i++)
_Translator.push(luaState, _LastCalledMethod.args[_LastCalledMethod.outList[index]]);
}
//by isSingle 2010-09-10 11:26:31
//Desc:
// if not return void,we need add 1,
// or we will lost the function's return value
// when call dotnet function like "int foo(arg1,out arg2,out arg3)" in lua code
if(!_LastCalledMethod.IsReturnVoid && nReturnValues > 0)
nReturnValues++;
return nReturnValues < 1 ? 1 : nReturnValues;
}
}
}
\ No newline at end of file
/*
* This file is part of LuaInterface.
*
* Copyright (C) 2003-2005 Fabio Mascarenhas de Queiroz.
* Copyright (C) 2012 Megax <http://megax.yeahunter.hu/>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
using System;
namespace LuaInterface.Method
{
/*
* Parameter information
*/
struct MethodArgs
{
// Position of parameter
public int index;
// Type-conversion function
public ExtractValue extractValue;
public bool isParamsArray;
public Type paramsArrayType;
}
/*
* This file is part of LuaInterface.
*
* Copyright (C) 2003-2005 Fabio Mascarenhas de Queiroz.
* Copyright (C) 2012 Megax <http://megax.yeahunter.hu/>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
using System;
namespace LuaInterface.Method
{
/*
* Parameter information
*/
struct MethodArgs
{
// Position of parameter
public int index;
// Type-conversion function
public ExtractValue extractValue;
public bool isParamsArray;
public Type paramsArrayType;
}
}
\ No newline at end of file
/*
* This file is part of LuaInterface.
*
* Copyright (C) 2003-2005 Fabio Mascarenhas de Queiroz.
* Copyright (C) 2012 Megax <http://megax.yeahunter.hu/>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
using System;
using System.Reflection;
using LuaInterface.Extensions;
namespace LuaInterface.Method
{
/*
* Cached method
*/
struct MethodCache
{
private MethodBase _cachedMethod;
public MethodBase cachedMethod
{
get
{
return _cachedMethod;
}
set
{
_cachedMethod = value;
var mi = value as MethodInfo;
if(!mi.IsNull())
IsReturnVoid = string.Compare(mi.ReturnType.Name, "System.Void", true) == 0;
}
}
public bool IsReturnVoid;
// List or arguments
public object[] args;
// Positions of out parameters
public int[] outList;
// Types of parameters
public MethodArgs[] argTypes;
}
/*
* This file is part of LuaInterface.
*
* Copyright (C) 2003-2005 Fabio Mascarenhas de Queiroz.
* Copyright (C) 2012 Megax <http://megax.yeahunter.hu/>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
using System;
using System.Reflection;
using LuaInterface.Extensions;
namespace LuaInterface.Method
{
/*
* Cached method
*/
struct MethodCache
{
private MethodBase _cachedMethod;
public MethodBase cachedMethod
{
get
{
return _cachedMethod;
}
set
{
_cachedMethod = value;
var mi = value as MethodInfo;
if(!mi.IsNull())
IsReturnVoid = string.Compare(mi.ReturnType.Name, "System.Void", true) == 0;
}
}
public bool IsReturnVoid;
// List or arguments
public object[] args;
// Positions of out parameters
public int[] outList;
// Types of parameters
public MethodArgs[] argTypes;
}
}
\ No newline at end of file
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment