Skip to content

Commit

Permalink
Implemented aliases for exported-functions and variables #9
Browse files Browse the repository at this point in the history
  • Loading branch information
3F committed Jan 19, 2017
1 parent 8e5a29c commit c676f47
Show file tree
Hide file tree
Showing 9 changed files with 302 additions and 3 deletions.
39 changes: 39 additions & 0 deletions Conari/Aliases/IAlias.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
/*
* The MIT License (MIT)
*
* Copyright (c) 2016-2017 Denis Kuzmin <entry.reg@gmail.com>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Conari"), 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.
*/

namespace net.r_eg.Conari.Aliases
{
public interface IAlias
{
/// <summary>
/// The final name.
/// </summary>
string Name { get; set; }

/// <summary>
/// Configuration of alias.
/// </summary>
IAliasCfg Cfg { get; }
}
}
31 changes: 31 additions & 0 deletions Conari/Aliases/IAliasCfg.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
/*
* The MIT License (MIT)
*
* Copyright (c) 2016-2017 Denis Kuzmin <entry.reg@gmail.com>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Conari"), 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.
*/

namespace net.r_eg.Conari.Aliases
{
public interface IAliasCfg
{
//TODO: PrefixL/R, the rules of mangling, ...
}
}
83 changes: 83 additions & 0 deletions Conari/Aliases/ProcAlias.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
/*
* The MIT License (MIT)
*
* Copyright (c) 2016-2017 Denis Kuzmin <entry.reg@gmail.com>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Conari"), 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 net.r_eg.Conari.Aliases
{
public struct ProcAlias: IAlias
{
/// <summary>
/// The final name.
/// </summary>
public string Name
{
get {
return _name;
}
set
{
if(String.IsNullOrWhiteSpace(value)) {
throw new ArgumentException("The value cannot be null or empty.");
}
_name = value;
}
}
private string _name;

/// <summary>
/// Configuration of alias.
/// </summary>
public IAliasCfg Cfg
{
get;
private set;
}

public static implicit operator string(ProcAlias pa)
{
return pa.Name;
}

public static implicit operator ProcAlias(string str)
{
return new ProcAlias() {
Name = str
};
}

public ProcAlias(string name)
: this()
{
Name = name;
}

// TODO: cfg
public ProcAlias(string name, IAliasCfg cfg)
: this(name)
{
Cfg = cfg;
}
}
}
3 changes: 3 additions & 0 deletions Conari/Conari.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,10 @@
<Reference Include="System.Core" />
</ItemGroup>
<ItemGroup>
<Compile Include="Aliases\IAliasCfg.cs" />
<Compile Include="Core\ExVar.cs" />
<Compile Include="Aliases\ProcAlias.cs" />
<Compile Include="Aliases\IAlias.cs" />
<Compile Include="Core\IExVar.cs" />
<Compile Include="Core\IDynamic.cs" />
<Compile Include="Core\IProviderSvc.cs" />
Expand Down
7 changes: 7 additions & 0 deletions Conari/Core/IProvider.cs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,9 @@
*/

using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using net.r_eg.Conari.Aliases;

namespace net.r_eg.Conari.Core
{
Expand Down Expand Up @@ -59,6 +61,11 @@ public interface IProvider: IBinder, IMem
/// </summary>
bool Mangling { get; set; }

/// <summary>
/// The aliases for exported-functions and variables.
/// </summary>
Dictionary<string, ProcAlias> Aliases { get; }

/// <summary>
/// Access to exported variables.
/// </summary>
Expand Down
25 changes: 24 additions & 1 deletion Conari/Core/Provider.cs
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
using System.Reflection;
using System.Reflection.Emit;
using System.Runtime.InteropServices;
using net.r_eg.Conari.Aliases;
using net.r_eg.Conari.Exceptions;
using net.r_eg.Conari.Log;
using net.r_eg.Conari.Native;
Expand Down Expand Up @@ -96,6 +97,15 @@ public bool Mangling
set;
}

/// <summary>
/// The aliases for exported-functions and variables.
/// </summary>
public Dictionary<string, ProcAlias> Aliases
{
get;
protected set;
} = new Dictionary<string, ProcAlias>();

/// <summary>
/// Access to exported variables.
/// </summary>
Expand Down Expand Up @@ -321,7 +331,7 @@ protected IntPtr getProcAddress(string lpProcName)
throw new LoaderException($"The handle of library is zero. Last loaded library: '{Library.LibName}'");
}

return getProcAddress(Library.Handle, lpProcName, Mangling);
return getProcAddress(Library.Handle, alias(lpProcName), Mangling);
}

protected IntPtr getProcAddress(IntPtr hModule, string lpProcName, bool mangling = true)
Expand Down Expand Up @@ -355,6 +365,19 @@ protected IntPtr getProcAddress(IntPtr hModule, string lpProcName, bool mangling
return getProcAddress(hModule, func, false);
}

protected string alias(string lpProcName)
{
if(Aliases == null || lpProcName == null
|| !Aliases.ContainsKey(lpProcName))
{
return lpProcName;
}
IAlias als = Aliases[lpProcName];

LSender.Send(this, $"Use alias '{als.Name}' instead of '{lpProcName}'", Message.Level.Info);
return als.Name;
}

protected T getDelegate<T>(string lpProcName) where T : class
{
return getDelegate<T>(getProcAddress(lpProcName));
Expand Down
102 changes: 102 additions & 0 deletions ConariTest/AliasesTest.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
using System;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using net.r_eg.Conari;
using net.r_eg.Conari.Aliases;
using net.r_eg.Conari.Core;
using net.r_eg.Conari.Types;

namespace net.r_eg.ConariTest
{
[TestClass]
public class AliasesTest
{
private const string UNLIB_DLL = "UnLib.dll";

[TestMethod]
public void aliasTest1()
{
// bool net::r_eg::Conari::UnLib::API::getD_True(void)
// ?getD_True@API@UnLib@Conari@r_eg@net@@YA_NXZ

using(var l = new ConariL(UNLIB_DLL))
{
l.Aliases["getD_True"] = new ProcAlias("?getD_True@API@UnLib@Conari@r_eg@net@@YA_NXZ");

Assert.AreEqual(true, l.DLR.getD_True<bool>());
Assert.AreEqual(true, l.bind<Func<bool>>("getD_True")());
Assert.AreEqual(true, l.bind(Dynamic.GetMethodInfo(typeof(bool)), "getD_True")
.dynamic
.Invoke(null, new object[0]));
}
}

[TestMethod]
public void aliasTest2()
{
// unsigned short net::r_eg::Conari::UnLib::API::getD_Seven(void)
// ?getD_Seven@API@UnLib@Conari@r_eg@net@@YAGXZ

using(var l = new ConariL(UNLIB_DLL))
{
l.Aliases["getD_Seven"] = new ProcAlias("?getD_Seven@API@UnLib@Conari@r_eg@net@@YAGXZ");

Assert.AreEqual(7, l.DLR.getD_Seven<ushort>());
Assert.AreEqual(7, l.bind<Func<ushort>>("getD_Seven")());
Assert.AreEqual((ushort)7, l.bind(Dynamic.GetMethodInfo(typeof(ushort)), "getD_Seven")
.dynamic
.Invoke(null, new object[0]));
}
}

[TestMethod]
public void aliasTest3()
{
// char const * net::r_eg::Conari::UnLib::API::getD_HelloWorld(void)
// ?getD_HelloWorld@API@UnLib@Conari@r_eg@net@@YAPBDXZ

using(var l = new ConariL(UNLIB_DLL))
{
string exp = "Hello World !";
l.Aliases["getD_HelloWorld"] = new ProcAlias("?getD_HelloWorld@API@UnLib@Conari@r_eg@net@@YAPBDXZ");

Assert.AreEqual(exp, l.DLR.getD_HelloWorld<CharPtr>());
Assert.AreEqual(exp, l.bind<Func<CharPtr>>("getD_HelloWorld")());

var dyn = l.bind(Dynamic.GetMethodInfo(typeof(CharPtr)), "getD_HelloWorld");
Assert.AreEqual(exp, (CharPtr)dyn.dynamic.Invoke(null, new object[0]));
}
}

[TestMethod]
public void multiAliasTest1()
{
using(var l = new ConariL(UNLIB_DLL))
{
l.Aliases["getD_True"] = "?getD_True@API@UnLib@Conari@r_eg@net@@YA_NXZ";
l.Aliases["getFlag"] = l.Aliases["getD_True"];

Assert.AreEqual(true, l.DLR.getD_True<bool>());
Assert.AreEqual(true, l.DLR.getFlag<bool>());
Assert.AreEqual(true, l.bind<Func<bool>>("getFlag")());
Assert.AreEqual(true, l.bind(Dynamic.GetMethodInfo(typeof(bool)), "getFlag")
.dynamic
.Invoke(null, new object[0]));
}
}

[TestMethod]
public void multiAliasTest2()
{
using(var l = new ConariL(UNLIB_DLL))
{
l.Aliases["d"] = "?getD_True@API@UnLib@Conari@r_eg@net@@YA_NXZ";
l.Aliases["a"] = l.Aliases["b"] = l.Aliases["c"] = l.Aliases["d"];

Assert.AreEqual(true, l.DLR.a<bool>());
Assert.AreEqual(true, l.DLR.b<bool>());
Assert.AreEqual(true, l.DLR.c<bool>());
Assert.AreEqual(true, l.DLR.d<bool>());
}
}
}
}
1 change: 1 addition & 0 deletions ConariTest/ConariTest.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@
</Otherwise>
</Choose>
<ItemGroup>
<Compile Include="AliasesTest.cs" />
<Compile Include="ExVarTest.cs" />
<Compile Include="BindingTest.cs" />
<Compile Include="Native\Core\RawTest.cs" />
Expand Down
14 changes: 12 additions & 2 deletions Readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
Binder of Unmanaged code for .NET

The Conari engine represents flexible platform for work with unmanaged code (native C/C++ etc.): Libraries, Executable Modules, other native and binary data.
Lightweight and powerful binding with any exported functions and much more.
Lightweight and powerful binding with any exported-functions/variables, and much more.

*Did you know: The [LunaRoad](https://github.com/3F/LunaRoad) project works via Conari engine.*

Expand Down Expand Up @@ -132,7 +132,7 @@ using(var l = new ConariL("Library.dll", CallingConvention.StdCall))
}
```

**Exported Variables & Raw access:**
**Exported Variables & Raw access [[?](https://github.com/3F/Conari/issues/7#issuecomment-269123650)]:**
```csharp
// v1.3+
Expand All @@ -143,6 +143,16 @@ l.Svc.native("lpProcName"); // Raw access via NativeData & Native.Core !
//v1.0+: Use Provider or ConariL frontend via your custom wrapper.
```

**Aliases for exported-functions and variables [[?](https://github.com/3F/Conari/issues/9)]:**
```csharp
// v1.3+
l.Aliases["getD_True"] = "?getD_True@API@UnLib@Conari@r_eg@net@@YA_NXZ";
l.Aliases["getFlag"] = l.Aliases["getD_True"]; // getFlag -> getD_True -> ...
// ...
l.Aliases["a"] = l.Aliases["b"] = l.Aliases["c"] = l.Aliases["d"];
```

**Additional types:**

* BSTR, CharPtr, float_t, int_t, ptrdiff_t, size_t, uint_t, WCharPtr
Expand Down

0 comments on commit c676f47

Please sign in to comment.