Home >
Uploads
C# Project Template for Unmanaged Exports
This template is obsolete now, just use the nuget package. Simply drop this archive into your "My Documents\Visual Studio 20**\Templates\ProjectTemplates". (Do not extract it) You don't have to be an administrator, this is only for your windows account, though. The next time you open the new project wizard, you should see a new project type directly under "Visual C#", with a Windows DLL icon. That's it. The projects created this way can be compiled by anyone who has Visual Studio 2005/2008 installed or just the .Net 2.0-3.X SDK. Which means it won't pose any problems with build servers or opening the project on different machines. Check out the Samples for more information. |
Unmanaged Exports
How does it work?Create a new classlibrary or proceed with an existing one. Then add the UnmanagedExports Nuget package. 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
SamplesBasic sampleShowing 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 sampleYou 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
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 :-) |
1-2 of 2