interop - 动态导入 C/C++ DLL

标签 interop f# pinvoke

据我所知,要在 F# 中使用 P/Invoke,必须首先使用 DllImport 声明函数签名,如下所示:

[<DllImport("kernel32.dll", EntryPoint="CopyFile")>]
extern bool copyfile(char[] lpExistingFile, char[] lpNewFile, bool bFailIfExists);

如果 DLL 名称在编译时已知,那就太好了。如果我只能在运行时发现名称,如何与非托管 C/C++ DLL 交互?

最佳答案

或者,您可以提出一个动态生成 PInvoke 方法的解决方案。

open System
open System.Reflection
open System.Reflection.Emit
open System.Runtime.InteropServices

let assembly = AppDomain.CurrentDomain.DefineDynamicAssembly (new AssemblyName ("PInvokeLibrary"), AssemblyBuilderAccess.Run)
let module_builder = assembly.DefineDynamicModule ("PInvokeLibrary")

let define_dynamic_pinvoke<'d when 'd :> Delegate> (name, library) =
  let invoke = typeof<'d>.GetMethod ("Invoke") (* signature of delegate 'd *)
  let parameters =
    invoke.GetParameters ()
    |> Array.map (fun p -> p.ParameterType)
  let type_builder = module_builder.DefineType (name, TypeAttributes.Public)
  let method_builder =
    type_builder.DefinePInvokeMethod (
      name,
      library,
      MethodAttributes.Public ||| MethodAttributes.Static ||| MethodAttributes.PinvokeImpl,
      CallingConventions.Standard,
      invoke.ReturnType,
      parameters,
      CallingConvention.Winapi,
      CharSet.Ansi)
  method_builder.SetImplementationFlags (method_builder.GetMethodImplementationFlags () ||| MethodImplAttributes.PreserveSig)
  let result_type = type_builder.CreateType ()
  let pinvoke = result_type.GetMethod (name)
  Delegate.CreateDelegate (typeof<'d>, pinvoke) :?> 'd

let beep = define_dynamic_pinvoke<Func<int, int, bool>> ("Beep", "kernel32.dll")

beep.Invoke (800, 100)

关于interop - 动态导入 C/C++ DLL,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1782610/

相关文章:

javascript - 连接端口和订阅时遇到问题

syntax - F# Constructed Type 语法是否特殊?

c# - 在 DllImport 中使用 Unicode 字符串和用 Rust 编写的 DLL

c# - 为什么 `[DllImport]` 会以 `RtlSecureZeroMemory` 的入口点失败,即使它是一个有据可查的入口点?

c# - 如何获取指向接口(interface)的指针?

java - 在 Java 中实现 Scala 特征时处理私有(private)字段

f# - F#中单子(monad)定律的解释

f# - fparsec 解析字符串序列

c# - 返回结构时,PInvoke 仅适用于 64 位

c# - 字符串数组 C# 与 C++ dll 的互操作性;从 C# 到 C++ dll 的字符串数组,它设置数据并将其发送回 c#