How does it work?
Create a new classlibrary or proceed with an existing one.
This is pretty much all setup that is required.
Now you can write any kind of static method, decorate it with [DllExport] and use it from native code.
It works just like DllImport, so you can customize the marshalling of parameters/result with
MarshalAsAttribute
.
During compilation, my task will modify the IL to add the required exports.
Restrictions
- What you cannot do is use overloaded exported methods inside the same class, even if you provide them with different export names.
- Another restriction is that you cannot call an exported method recursively.
- This seems to be a limitation of the runtime and I did not want to wrap your code in another, hidden method to make it work.
Samples
Basic sample
Showing how to provide an export alias (the name which will be seen from consuming processes) and calling convention. (Default is stdcall, the samples use Cdecl which is used by C/C++)
C#:
class Test
{
[DllExport(
"add", CallingConvention = CallingConvention.
Cdecl
)]
public static int
TestExport
(int left, int right)
{
return left + right;
}
}
F#:
open
RGiesecke.DllExport
open System.Runtime.InteropServices
type Test() =
[<DllExport("add", CallingConvention = CallingConvention.Cdecl)>]
static member
TestExport
(left : int, right : int) : int = left + right
VB.Net:
Imports
System.Runtime.InteropServices
Imports RGiesecke.DllExport
Public Module Test
<DllExport("add")> _
Public Function TestExport(left As Int32, right As Int32) As Int32
Return left + right
End Function
End Module
Marshalling sample
You can also use the MarshalAsAttribute to control how the marshaller translates your .Net types into native types.
The example below shows how to mark a parameter to be returned to native code as an IUnknown-compatible interface reference.
btw, this is also how to pass objects between native and .Net ;-)
[
ComVisible(
true)]
[
Guid(
"Some GUID"),
InterfaceType(
ComInterfaceType.InterfaceIsIUnknown)]
public interface ISample
{
// without MarshalAs(UnmanagedType.BStr), .Net will marshal these strings as single-byte Ansi!
// BStr is equivalent to Delphi's WideString
String Name
{
// this is how to add attributes to a getter's result parameter
[
return:
MarshalAs(
UnmanagedType.BStr)]
get;
// this is how to add attributes to a setter's value parameter
[
param:
MarshalAs(
UnmanagedType.BStr)]
set;
}
int DoSomething(
int value);
}
public class
Sample :
ISample
{
public
String Name{
get;
set; }
public int DoSomething(
int value)
{
return value + 1;
}
}
static class
Exports
{
[
DllExport]
public static void CreateSampleInstance([
MarshalAs(
UnmanagedType.Interface)]
out
ISample instance)
{
instance =
new
Sample{ Name =
"Test" };
}
}
Changes
- Deployed as nuget package!
- Should install itself nicely over existing projects
- no longer limited to C#!
- pretty much any sane language that can create static methods with attributes should work
- VS 2008 is no longer supported (it has no nuget support)
- Also applies to Sharpdevelop 4.2, because my nuget scripts don't work in this version.
- Various fixes regarding path reslution for ildasm.exe, ilasm.exe and lib.exe
- it will no longer fail if it can't find lib.exe (it just won't produce .lib & .def files)
- export names are escaped, so using il keywords like add won't be a problem any more
- The task will only execute when you have selected a specific CPU target (x86, x64, Itanium) in your build options
- Creating sub folders for each target was kinda creepy and VS' project references went crazy
- Build events will now be fired after my task has finished (thx to Darin Higgins)
- Uses a newer version of Mono.Cecil (0.9.5) to look for attributes
- Version 1.1.3
- In VS2008 and VS2010, the correct version of ILAsm/ILDasm will be used according to the TargetFramework. Only important for 2010 due to 4.0 / 2.0 runtime.
- Temporary .def file will be removed as it isn't really required after having the .lib and .exp file.
- Fixes to the .lib creation (export names had the real method name in the .lib, not the one that DllExport contained, while the DLL itself exported it correctly)
- nicer Icon
- TargetFramework is no longer set to 3.5 but left empty for the IDE to decide what makes sense (VS2005 obviously has no clue about this setting).
- Autom. packaging of the C# project template and the archive on this page during build, to prevent uploading older versions.
Version 1.1.2
- When provided with the location of lib.exe, it will create the .lib and .exp files that are required my MSVC
- either autom. inside the VS IDE
- having an environmental variable LibToolPath pointed to its directory
- or adding a property LibToolPath to the project file
- Version 1.1.1
- I created a C# project template to make it very, very easy to setup the target and build task.
- I also fixed some issues that could result in extreme slowdowns.
- When you use the same export name for multiple methods, it will now create a warning which uses the pdb debug infos to point to the exact source locations.
License
Old Downloads removed...
The old downloads were removed, please use Nuget.
I went pretty far to make those install/uninstall scripts work nicely and undestructively, so please do use them :-)