NativeMethods.cs 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240
  1. using System.Diagnostics;
  2. using System.Runtime.InteropServices;
  3. using OpenCvSharp.Internal.Util;
  4. #if DOTNET_FRAMEWORK
  5. using System.Security;
  6. using System.Security.Permissions;
  7. #endif
  8. // TODO
  9. #pragma warning disable CA5393
  10. [assembly: DefaultDllImportSearchPaths(DllImportSearchPath.LegacyBehavior)]
  11. // ReSharper disable InconsistentNaming
  12. #pragma warning disable 1591
  13. #pragma warning disable CA1805 // Do not initialize unnecessarily.
  14. namespace OpenCvSharp.Internal;
  15. /// <summary>
  16. /// P/Invoke methods of OpenCV 2.x C++ interface
  17. /// </summary>
  18. #if DOTNET_FRAMEWORK
  19. [SuppressUnmanagedCodeSecurity]
  20. #endif
  21. public static partial class NativeMethods
  22. {
  23. public const string DllExtern = "OpenCvSharpExtern.dll";
  24. //public const string DllFfmpegX86 = "opencv_videoio_ffmpeg430";
  25. //public const string DllFfmpegX64 = "opencv_videoio_ffmpeg430_64";
  26. //private const UnmanagedType StringUnmanagedType = UnmanagedType.LPStr;
  27. private const UnmanagedType StringUnmanagedTypeWindows = UnmanagedType.LPStr;
  28. private const UnmanagedType StringUnmanagedTypeNotWindows =
  29. #if NET48 || NETSTANDARD2_0
  30. UnmanagedType.LPStr;
  31. #else
  32. UnmanagedType.LPUTF8Str;
  33. #endif
  34. /// <summary>
  35. /// Is tried P/Invoke once
  36. /// </summary>
  37. private static bool tried;
  38. /// <summary>
  39. /// Static constructor
  40. /// </summary>
  41. #if DOTNET_FRAMEWORK
  42. [SecurityPermission(SecurityAction.Demand, Flags = SecurityPermissionFlag.UnmanagedCode)]
  43. #endif
  44. static NativeMethods()
  45. {
  46. LoadLibraries(WindowsLibraryLoader.Instance.AdditionalPaths);
  47. // call cv to enable redirecting
  48. TryPInvoke();
  49. }
  50. #pragma warning disable CA1801
  51. public static void HandleException(ExceptionStatus status)
  52. {
  53. #if DOTNETCORE
  54. // Check if there has been an exception
  55. if (status == ExceptionStatus.Occurred /*&& IsUnix()*/) // thrown can be 1 when unix
  56. {
  57. ExceptionHandler.ThrowPossibleException();
  58. }
  59. #else
  60. #endif
  61. }
  62. #pragma warning restore CA1801
  63. /// <summary>
  64. /// Load DLL files dynamically using Win32 LoadLibrary
  65. /// </summary>
  66. /// <param name="additionalPaths"></param>
  67. public static void LoadLibraries(IEnumerable<string>? additionalPaths = null)
  68. {
  69. if (IsWasm())
  70. {
  71. return;
  72. }
  73. if (IsUnix())
  74. {
  75. #if DOTNETCORE
  76. ExceptionHandler.RegisterExceptionCallback();
  77. #endif
  78. return;
  79. }
  80. var ap = (additionalPaths is null) ? Array.Empty<string>() : additionalPaths.ToArray();
  81. /*
  82. if (Environment.Is64BitProcess)
  83. WindowsLibraryLoader.Instance.LoadLibrary(DllFfmpegX64, ap);
  84. else
  85. WindowsLibraryLoader.Instance.LoadLibrary(DllFfmpegX86, ap);
  86. //*/
  87. WindowsLibraryLoader.Instance.LoadLibrary(DllExtern, ap);
  88. // Redirection of error occurred in native library
  89. var zero = IntPtr.Zero;
  90. var current = redirectError(ErrorHandlerThrowException, zero, ref zero);
  91. GC.KeepAlive(current);
  92. }
  93. /// <summary>
  94. /// Checks whether PInvoke functions can be called
  95. /// </summary>
  96. public static void TryPInvoke()
  97. {
  98. #pragma warning disable CA1031
  99. if (tried)
  100. return;
  101. tried = true;
  102. try
  103. {
  104. var ret = core_Mat_sizeof();
  105. GC.KeepAlive(ret);
  106. }
  107. catch (DllNotFoundException e)
  108. {
  109. var exception = PInvokeHelper.CreateException(e);
  110. try{Console.WriteLine(exception.Message); }
  111. // ReSharper disable once EmptyGeneralCatchClause
  112. catch { }
  113. try{Debug.WriteLine(exception.Message); }
  114. // ReSharper disable once EmptyGeneralCatchClause
  115. catch { }
  116. throw exception;
  117. }
  118. catch (BadImageFormatException e)
  119. {
  120. var exception = PInvokeHelper.CreateException(e);
  121. try { Console.WriteLine(exception.Message); }
  122. // ReSharper disable once EmptyGeneralCatchClause
  123. catch { }
  124. try { Debug.WriteLine(exception.Message); }
  125. // ReSharper disable once EmptyGeneralCatchClause
  126. catch { }
  127. throw exception;
  128. }
  129. catch (Exception e)
  130. {
  131. var ex = e.InnerException ?? e;
  132. try{ Console.WriteLine(ex.Message); }
  133. // ReSharper disable once EmptyGeneralCatchClause
  134. catch { }
  135. try { Debug.WriteLine(ex.Message); }
  136. // ReSharper disable once EmptyGeneralCatchClause
  137. catch { }
  138. throw;
  139. }
  140. #pragma warning restore CA1031
  141. }
  142. /// <summary>
  143. /// Returns whether the OS is Windows or not
  144. /// </summary>
  145. /// <returns></returns>
  146. public static bool IsWindows()
  147. {
  148. #if NET48
  149. return !IsUnix();
  150. #else
  151. return RuntimeInformation.IsOSPlatform(OSPlatform.Windows);
  152. #endif
  153. }
  154. /// <summary>
  155. /// Returns whether the OS is *nix or not
  156. /// </summary>
  157. /// <returns></returns>
  158. public static bool IsUnix()
  159. {
  160. #if NET48
  161. var p = Environment.OSVersion.Platform;
  162. return (p == PlatformID.Unix ||
  163. p == PlatformID.MacOSX ||
  164. (int)p == 128);
  165. #elif NETCOREAPP3_1_OR_GREATER
  166. return RuntimeInformation.IsOSPlatform(OSPlatform.Linux) ||
  167. RuntimeInformation.IsOSPlatform(OSPlatform.OSX) ||
  168. RuntimeInformation.IsOSPlatform(OSPlatform.FreeBSD);
  169. #else
  170. return RuntimeInformation.IsOSPlatform(OSPlatform.Linux) ||
  171. RuntimeInformation.IsOSPlatform(OSPlatform.OSX);
  172. #endif
  173. }
  174. /// <summary>
  175. /// Returns whether the runtime is Mono or not
  176. /// </summary>
  177. /// <returns></returns>
  178. public static bool IsMono()
  179. {
  180. return (Type.GetType("Mono.Runtime") is not null);
  181. }
  182. /// <summary>
  183. /// Returns whether the architecture is Wasm or not
  184. /// </summary>
  185. /// <returns></returns>
  186. public static bool IsWasm()
  187. {
  188. #if NET6_0
  189. return RuntimeInformation.OSArchitecture == Architecture.Wasm;
  190. #else
  191. return false;
  192. #endif
  193. }
  194. /// <summary>
  195. /// Custom error handler to be thrown by OpenCV
  196. /// </summary>
  197. public static readonly CvErrorCallback ErrorHandlerThrowException =
  198. // ReSharper disable once UnusedParameter.Local
  199. (status, funcName, errMsg, fileName, line, userData) => throw new OpenCVException(status, funcName, errMsg, fileName, line);
  200. /// <summary>
  201. /// Custom error handler to ignore all OpenCV errors
  202. /// </summary>
  203. // ReSharper disable UnusedParameter.Local
  204. public static readonly CvErrorCallback ErrorHandlerIgnorance =
  205. (status, funcName, errMsg, fileName, line, userData) => 0;
  206. // ReSharper restore UnusedParameter.Local
  207. #pragma warning disable CA2211
  208. /// <summary>
  209. /// Default error handler
  210. /// </summary>
  211. public static CvErrorCallback? ErrorHandlerDefault = null;
  212. #pragma warning restore CA2211
  213. }