zoukankan      html  css  js  c++  java
  • C#互操作(C# 调用动态库)

    很多时候需要调用其它语言生成的动态库,那么 c# 如何调用动态库呢
    下面简单介绍 C# 调用 c 语言生成的动态库

    func.c

    int add(int num1,int num2)
    {
        return num1 + num2;
    }
    

    编译生成动态库文件

    gcc -fPIC -shared func.c -o libfunc.so
    

    c# 代码

    using System;
    using System.Runtime.InteropServices;
    
    namespace Domain
    {
        class Program
        {
            static void Main(string[] args)
            {
                var num = Func.Add(1, 2);
                Console.WriteLine("Hello World {0}!", num);
            }
        }
    
        public class Func
        {
    
            [DllImport("libfunc", EntryPoint = "add")]
            public static extern int Add(int num1, int num2);
    
        }
    }
    
    

    编译 dotnet 程序,将 dotnet 程序和 动态库放在同一目录下(确保动态库能被找到) 可以设置环境变量 LD_LIBRARY_PATH (基本知识需要自己补充)

    输出

    Hello World 3!
    
    

    文档

    高级用法

    MsQuicApi.cs

    // Licensed to the .NET Foundation under one or more agreements.
    // The .NET Foundation licenses this file to you under the MIT license.
    
    using System.Diagnostics.CodeAnalysis;
    using System.Runtime.InteropServices;
    using static System.Net.Quic.Implementations.MsQuic.Internal.MsQuicNativeMethods;
    
    namespace System.Net.Quic.Implementations.MsQuic.Internal
    {
        internal unsafe sealed class MsQuicApi
        {
            private static readonly Version MinWindowsVersion = new Version(10, 0, 20145, 1000);
    
            public SafeMsQuicRegistrationHandle Registration { get; }
    
            // This is workaround for a bug in ILTrimmer.
            // Without these DynamicDependency attributes, .ctor() will be removed from the safe handles.
            // Remove once fixed: https://github.com/mono/linker/issues/1660
            [DynamicDependency(DynamicallyAccessedMemberTypes.NonPublicConstructors, typeof(SafeMsQuicRegistrationHandle))]
            [DynamicDependency(DynamicallyAccessedMemberTypes.NonPublicConstructors, typeof(SafeMsQuicConfigurationHandle))]
            [DynamicDependency(DynamicallyAccessedMemberTypes.NonPublicConstructors, typeof(SafeMsQuicListenerHandle))]
            [DynamicDependency(DynamicallyAccessedMemberTypes.NonPublicConstructors, typeof(SafeMsQuicConnectionHandle))]
            [DynamicDependency(DynamicallyAccessedMemberTypes.NonPublicConstructors, typeof(SafeMsQuicStreamHandle))]
            private MsQuicApi(NativeApi* vtable)
            {
                uint status;
    
                SetParamDelegate =
                    Marshal.GetDelegateForFunctionPointer<SetParamDelegate>(
                        vtable->SetParam);
    
                GetParamDelegate =
                    Marshal.GetDelegateForFunctionPointer<GetParamDelegate>(
                        vtable->GetParam);
    
                SetCallbackHandlerDelegate =
                    Marshal.GetDelegateForFunctionPointer<SetCallbackHandlerDelegate>(
                        vtable->SetCallbackHandler);
    
                RegistrationOpenDelegate =
                    Marshal.GetDelegateForFunctionPointer<RegistrationOpenDelegate>(
                        vtable->RegistrationOpen);
                RegistrationCloseDelegate =
                    Marshal.GetDelegateForFunctionPointer<RegistrationCloseDelegate>(
                        vtable->RegistrationClose);
    
                ConfigurationOpenDelegate =
                    Marshal.GetDelegateForFunctionPointer<ConfigurationOpenDelegate>(
                        vtable->ConfigurationOpen);
                ConfigurationCloseDelegate =
                    Marshal.GetDelegateForFunctionPointer<ConfigurationCloseDelegate>(
                        vtable->ConfigurationClose);
                ConfigurationLoadCredentialDelegate =
                    Marshal.GetDelegateForFunctionPointer<ConfigurationLoadCredentialDelegate>(
                        vtable->ConfigurationLoadCredential);
    
                ListenerOpenDelegate =
                    Marshal.GetDelegateForFunctionPointer<ListenerOpenDelegate>(
                        vtable->ListenerOpen);
                ListenerCloseDelegate =
                    Marshal.GetDelegateForFunctionPointer<ListenerCloseDelegate>(
                        vtable->ListenerClose);
                ListenerStartDelegate =
                    Marshal.GetDelegateForFunctionPointer<ListenerStartDelegate>(
                        vtable->ListenerStart);
                ListenerStopDelegate =
                    Marshal.GetDelegateForFunctionPointer<ListenerStopDelegate>(
                        vtable->ListenerStop);
    
                ConnectionOpenDelegate =
                    Marshal.GetDelegateForFunctionPointer<ConnectionOpenDelegate>(
                        vtable->ConnectionOpen);
                ConnectionCloseDelegate =
                    Marshal.GetDelegateForFunctionPointer<ConnectionCloseDelegate>(
                        vtable->ConnectionClose);
                ConnectionSetConfigurationDelegate =
                    Marshal.GetDelegateForFunctionPointer<ConnectionSetConfigurationDelegate>(
                        vtable->ConnectionSetConfiguration);
                ConnectionShutdownDelegate =
                    Marshal.GetDelegateForFunctionPointer<ConnectionShutdownDelegate>(
                        vtable->ConnectionShutdown);
                ConnectionStartDelegate =
                    Marshal.GetDelegateForFunctionPointer<ConnectionStartDelegate>(
                        vtable->ConnectionStart);
    
                StreamOpenDelegate =
                    Marshal.GetDelegateForFunctionPointer<StreamOpenDelegate>(
                        vtable->StreamOpen);
                StreamCloseDelegate =
                    Marshal.GetDelegateForFunctionPointer<StreamCloseDelegate>(
                        vtable->StreamClose);
                StreamStartDelegate =
                    Marshal.GetDelegateForFunctionPointer<StreamStartDelegate>(
                        vtable->StreamStart);
                StreamShutdownDelegate =
                    Marshal.GetDelegateForFunctionPointer<StreamShutdownDelegate>(
                        vtable->StreamShutdown);
                StreamSendDelegate =
                    Marshal.GetDelegateForFunctionPointer<StreamSendDelegate>(
                        vtable->StreamSend);
                StreamReceiveCompleteDelegate =
                    Marshal.GetDelegateForFunctionPointer<StreamReceiveCompleteDelegate>(
                        vtable->StreamReceiveComplete);
                StreamReceiveSetEnabledDelegate =
                    Marshal.GetDelegateForFunctionPointer<StreamReceiveSetEnabledDelegate>(
                        vtable->StreamReceiveSetEnabled);
    
                var cfg = new RegistrationConfig
                {
                    AppName = ".NET",
                    ExecutionProfile = QUIC_EXECUTION_PROFILE.QUIC_EXECUTION_PROFILE_LOW_LATENCY
                };
    
                status = RegistrationOpenDelegate(ref cfg, out SafeMsQuicRegistrationHandle handle);
                QuicExceptionHelpers.ThrowIfFailed(status, "RegistrationOpen failed.");
    
                Registration = handle;
            }
    
            internal static MsQuicApi Api { get; } = null!;
    
            internal static bool IsQuicSupported { get; }
    
            private const int MsQuicVersion = 1;
    
            static MsQuicApi()
            {
                if (OperatingSystem.IsWindows() && !IsWindowsVersionSupported())
                {
                    IsQuicSupported = false;
    
                    if (NetEventSource.Log.IsEnabled())
                    {
                        NetEventSource.Info(null, $"Current Windows version ({Environment.OSVersion}) is not supported by QUIC. Minimal supported version is {MinWindowsVersion}");
                    }
    
                    return;
                }
                
    
                // 重点这里 加载库 
                if (NativeLibrary.TryLoad(Interop.Libraries.MsQuic, typeof(MsQuicApi).Assembly, DllImportSearchPath.AssemblyDirectory, out IntPtr msQuicHandle))
                {
                    try
                    {
                       // 得到动态库函数指针
                        if (NativeLibrary.TryGetExport(msQuicHandle, "MsQuicOpenVersion", out IntPtr msQuicOpenVersionAddress))
                        {
                            delegate* unmanaged[Cdecl]<uint, out NativeApi*, uint> msQuicOpenVersion =
                                (delegate* unmanaged[Cdecl]<uint, out NativeApi*, uint>)msQuicOpenVersionAddress;
                            // 通过这个辅助函数返回所有 api 结构体指针
                            uint status = msQuicOpenVersion(MsQuicVersion, out NativeApi* vtable);
                            if (MsQuicStatusHelper.SuccessfulStatusCode(status))
                            {
                                IsQuicSupported = true;
                                // 结构体指针 还原到 包含c# 委托属性的类
                                Api = new MsQuicApi(vtable);
                            }
                        }
                    }
                    finally
                    {
                        if (!IsQuicSupported)
                        {
                            NativeLibrary.Free(msQuicHandle);
                        }
                    }
                }
            }
    
            private static bool IsWindowsVersionSupported() => OperatingSystem.IsWindowsVersionAtLeast(MinWindowsVersion.Major,
                MinWindowsVersion.Minor, MinWindowsVersion.Build, MinWindowsVersion.Revision);
    
            // TODO: Consider updating all of these delegates to instead use function pointers.
            internal RegistrationOpenDelegate RegistrationOpenDelegate { get; }
            internal RegistrationCloseDelegate RegistrationCloseDelegate { get; }
    
            internal ConfigurationOpenDelegate ConfigurationOpenDelegate { get; }
            internal ConfigurationCloseDelegate ConfigurationCloseDelegate { get; }
            internal ConfigurationLoadCredentialDelegate ConfigurationLoadCredentialDelegate { get; }
    
            internal ListenerOpenDelegate ListenerOpenDelegate { get; }
            internal ListenerCloseDelegate ListenerCloseDelegate { get; }
            internal ListenerStartDelegate ListenerStartDelegate { get; }
            internal ListenerStopDelegate ListenerStopDelegate { get; }
    
            // TODO: missing SendResumptionTicket
            internal ConnectionOpenDelegate ConnectionOpenDelegate { get; }
            internal ConnectionCloseDelegate ConnectionCloseDelegate { get; }
            internal ConnectionShutdownDelegate ConnectionShutdownDelegate { get; }
            internal ConnectionStartDelegate ConnectionStartDelegate { get; }
            internal ConnectionSetConfigurationDelegate ConnectionSetConfigurationDelegate { get; }
    
            internal StreamOpenDelegate StreamOpenDelegate { get; }
            internal StreamCloseDelegate StreamCloseDelegate { get; }
            internal StreamStartDelegate StreamStartDelegate { get; }
            internal StreamShutdownDelegate StreamShutdownDelegate { get; }
            internal StreamSendDelegate StreamSendDelegate { get; }
            internal StreamReceiveCompleteDelegate StreamReceiveCompleteDelegate { get; }
            internal StreamReceiveSetEnabledDelegate StreamReceiveSetEnabledDelegate { get; }
    
            internal SetCallbackHandlerDelegate SetCallbackHandlerDelegate { get; }
    
            internal SetParamDelegate SetParamDelegate { get; }
            internal GetParamDelegate GetParamDelegate { get; }
        }
    }
    
    
        internal static unsafe class MsQuicNativeMethods
        {
            [StructLayout(LayoutKind.Sequential)]
            internal struct NativeApi
            {
                internal IntPtr SetContext;
                internal IntPtr GetContext;
                internal IntPtr SetCallbackHandler;
    
                internal IntPtr SetParam;
                internal IntPtr GetParam;
    
                internal IntPtr RegistrationOpen;
                internal IntPtr RegistrationClose;
                internal IntPtr RegistrationShutdown;
    
                internal IntPtr ConfigurationOpen;
                internal IntPtr ConfigurationClose;
                internal IntPtr ConfigurationLoadCredential;
    
                internal IntPtr ListenerOpen;
                internal IntPtr ListenerClose;
                internal IntPtr ListenerStart;
                internal IntPtr ListenerStop;
    
                internal IntPtr ConnectionOpen;
                internal IntPtr ConnectionClose;
                internal IntPtr ConnectionShutdown;
                internal IntPtr ConnectionStart;
                internal IntPtr ConnectionSetConfiguration;
                internal IntPtr ConnectionSendResumptionTicket;
    
                internal IntPtr StreamOpen;
                internal IntPtr StreamClose;
                internal IntPtr StreamStart;
                internal IntPtr StreamShutdown;
                internal IntPtr StreamSend;
                internal IntPtr StreamReceiveComplete;
                internal IntPtr StreamReceiveSetEnabled;
    
                internal IntPtr DatagramSend;
            }
    
  • 相关阅读:
    hdu 1203 I NEED A OFFER!
    数据表示范围
    1936 哪一瓶是毒药?
    注册会计师带你用Python进行探索性风险分析(一)
    网络编程1 初识网络编程
    优秀技术网站汇总:
    DNS(域名系统)
    如何查看电脑网页的源码以及编码方式的位置?
    推荐一款播放器
    我的北大之路(贺舒婷)
  • 原文地址:https://www.cnblogs.com/microestc/p/14955261.html
Copyright © 2011-2022 走看看