C#导出非托管方法供C/C++调用

来源:互联网 发布:最好的sql语句教程 编辑:程序博客网 时间:2024/05/16 01:19

    最近研究Notepad++插件开发,由于Notepad++使用C++开发,Notepad++也提供了C#的开发接口http://notepad-plus-plus.org/contribute/plugin-howto.html ,根据官方提供的Visual Studio模板,里面用到C#导出非托管dll的知识。



     网上找到一个类似的第三方包Nuget package. 功能与此类似。
========================================================================================

以下部分原文地址:

https://sites.google.com/site/robertgiesecke/Home/uploads/unmanagedexports


Unmanaged Exports


Contents

  1. How does it work? 
    1. 1.1 Restrictions
  2. Samples
    1. 2.1 Basic sample
    2. 2.2 C#:
    3. 2.3 F#:
    4. 2.4 VB.Net:
    5. 2.5 Marshalling sample
  3. Changes
    1. 3.1 Version 1.2.1
    2. 3.2 Version 1.1.2
  4. Old Downloads removed...
  5. Donation



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

  • 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 Int32As 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
     [returnMarshalAs(UnmanagedType.BStr)]
     get;
     // this is how to add attributes to a setter's value parameter
     [paramMarshalAs(UnmanagedType.BStr)]
     set;
   }

   int DoSomething(int value);
}

public class Sample : ISample
{
   public String Name{ getset; }

   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

  • Version 1.2.1

    • 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
  1. MIT-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 :-)
0 0
原创粉丝点击