请选择 进入手机版 | 继续访问电脑版

[C 语言] C++ 封装 DLL 供 C# 调用具体 先容

[复制链接]
查看95 | 回复8 | 2021-9-14 08:21:57 | 显示全部楼层 |阅读模式
目次

1、VLC代码封装

1.1 QT(C++)工程

起首 必要 设置 可利用 VLC 正常播放的 QT(C++)工程,获取VLC每一帧并渲染到Qwidget

Libvlcapi

  1. public static class LIBVLCAPI
  2. {
  3. #region[libvlc.dll 导出函数]
  4. // 创建一个libvlc实例,它是引用计数的
  5. [DllImport("libvlc", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
  6. [SuppressUnmanagedCodeSecurity]
  7. private static extern IntPtr libvlc_new(int argc, IntPtr argv);
  8. // 释放libvlc实例
  9. [DllImport("libvlc", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
  10. [SuppressUnmanagedCodeSecurity]
  11. public static extern void libvlc_release(IntPtr libvlc_instance);
  12. [DllImport("libvlc", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
  13. [SuppressUnmanagedCodeSecurity]
  14. public static extern String libvlc_get_version();
  15. // 从视频来源(例如Url)构建一个libvlc_meida
  16. [DllImport("libvlc", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
  17. [SuppressUnmanagedCodeSecurity]
  18. private static extern IntPtr libvlc_media_new_location(IntPtr libvlc_instance, IntPtr path);
  19. // 从视频来源(例如Url)抓图
  20. [DllImport("libvlc", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
  21. [SuppressUnmanagedCodeSecurity]
  22. private static extern int libvlc_video_take_snapshot(IntPtr libvlc_mediaplayer, int num, IntPtr filepath, int i_width, int i_height);
  23. // 从本地文件路径构建一个libvlc_media
  24. [DllImport("libvlc", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
  25. [SuppressUnmanagedCodeSecurity]
  26. private static extern IntPtr libvlc_media_new_path(IntPtr libvlc_instance, IntPtr path);
  27. [DllImport("libvlc", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
  28. [SuppressUnmanagedCodeSecurity]
  29. public static extern void libvlc_media_release(IntPtr libvlc_media_inst);
  30. // 创建libvlc_media_player(播放核心)
  31. [DllImport("libvlc", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
  32. [SuppressUnmanagedCodeSecurity]
  33. public static extern IntPtr libvlc_media_player_new(IntPtr libvlc_instance);
  34. // 将视频(libvlc_media)绑定到播放器上
  35. [DllImport("libvlc", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
  36. [SuppressUnmanagedCodeSecurity]
  37. public static extern void libvlc_media_player_set_media(IntPtr libvlc_media_player, IntPtr libvlc_media);
  38. // 设置图像输出的窗口
  39. [DllImport("libvlc", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
  40. [SuppressUnmanagedCodeSecurity]
  41. public static extern void libvlc_media_player_set_hwnd(IntPtr libvlc_mediaplayer, Int32 drawable);
  42. [DllImport("libvlc", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
  43. [SuppressUnmanagedCodeSecurity]
  44. public static extern void libvlc_media_player_play(IntPtr libvlc_mediaplayer);
  45. [DllImport("libvlc", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
  46. [SuppressUnmanagedCodeSecurity]
  47. public static extern void libvlc_media_player_pause(IntPtr libvlc_mediaplayer);
  48. [DllImport("libvlc", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
  49. [SuppressUnmanagedCodeSecurity]
  50. public static extern void libvlc_media_player_stop(IntPtr libvlc_mediaplayer);
  51. // 解析视频资源的媒体信息(如时长等)
  52. [DllImport("libvlc", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
  53. [SuppressUnmanagedCodeSecurity]
  54. public static extern void libvlc_media_parse(IntPtr libvlc_media);
  55. // 返回视频的时长(必须先调用libvlc_media_parse之后,该函数才会生效)
  56. [DllImport("libvlc", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
  57. [SuppressUnmanagedCodeSecurity]
  58. public static extern Int64 libvlc_media_get_duration(IntPtr libvlc_media);
  59. // 当前播放的时间
  60. [DllImport("libvlc", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
  61. [SuppressUnmanagedCodeSecurity]
  62. public static extern Int64 libvlc_media_player_get_time(IntPtr libvlc_mediaplayer);
  63. // 设置播放位置(拖动)
  64. [DllImport("libvlc", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
  65. [SuppressUnmanagedCodeSecurity]
  66. public static extern void libvlc_media_player_set_time(IntPtr libvlc_mediaplayer, Int64 time);
  67. [DllImport("libvlc", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
  68. [SuppressUnmanagedCodeSecurity]
  69. public static extern void libvlc_media_player_release(IntPtr libvlc_mediaplayer);
  70. // 获取和设置音量
  71. [DllImport("libvlc", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
  72. [SuppressUnmanagedCodeSecurity]
  73. public static extern int libvlc_audio_get_volume(IntPtr libvlc_media_player);
  74. [DllImport("libvlc", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
  75. [SuppressUnmanagedCodeSecurity]
  76. public static extern void libvlc_audio_set_volume(IntPtr libvlc_media_player, int volume);
  77. // 设置全屏
  78. [DllImport("libvlc", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
  79. [SuppressUnmanagedCodeSecurity]
  80. public static extern void libvlc_set_fullscreen(IntPtr libvlc_media_player, int isFullScreen);
  81. // 设置屏幕因子
  82. [DllImport("libvlc", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
  83. [SuppressUnmanagedCodeSecurity]
  84. public static extern void libvlc_video_set_scale(IntPtr libvlc_media_player, float f_factor);
  85. #endregion
  86. #region[VLC方法]
  87. public struct PointerToArrayOfPointerHelper
  88. {
  89. [MarshalAs(UnmanagedType.ByValArray, SizeConst = 11)]
  90. public IntPtr[] pointers;
  91. }
  92. public static IntPtr libvlc_new(string[] arguments)
  93. {
  94. PointerToArrayOfPointerHelper argv = new PointerToArrayOfPointerHelper();
  95. argv.pointers = new IntPtr[11];
  96. for (int i = 0; i < arguments.Length; i++)
  97. {
  98. argv.pointers[i] = Marshal.StringToHGlobalAnsi(arguments[i]);
  99. }
  100. IntPtr argvPtr = IntPtr.Zero;
  101. try
  102. {
  103. int size = Marshal.SizeOf(typeof(PointerToArrayOfPointerHelper));
  104. argvPtr = Marshal.AllocHGlobal(size);
  105. Marshal.StructureToPtr(argv, argvPtr, false);
  106. return libvlc_new(arguments.Length, argvPtr);
  107. }
  108. finally
  109. {
  110. for (int i = 0; i < arguments.Length + 1; i++)
  111. {
  112. if (argv.pointers[i] != IntPtr.Zero)
  113. {
  114. Marshal.FreeHGlobal(argv.pointers[i]);
  115. }
  116. }
  117. if (argvPtr != IntPtr.Zero)
  118. {
  119. Marshal.FreeHGlobal(argvPtr);
  120. }
  121. }
  122. }
  123. public static IntPtr libvlc_media_new_path(IntPtr libvlc_instance, string path)
  124. {
  125. IntPtr pMrl = IntPtr.Zero;
  126. try
  127. {
  128. byte[] bytes = Encoding.UTF8.GetBytes(path);
  129. pMrl = Marshal.AllocHGlobal(bytes.Length + 1);
  130. Marshal.Copy(bytes, 0, pMrl, bytes.Length);
  131. Marshal.WriteByte(pMrl, bytes.Length, 0);
  132. return libvlc_media_new_path(libvlc_instance, pMrl);
  133. }
  134. finally
  135. {
  136. if (pMrl != IntPtr.Zero)
  137. {
  138. Marshal.FreeHGlobal(pMrl);
  139. }
  140. }
  141. }
  142. public static int libvlc_video_take_snapshot(IntPtr libvlc_mediaplayer, int num, string path, int width, int height)
  143. {
  144. IntPtr pMrl = IntPtr.Zero;
  145. try
  146. {
  147. byte[] bytes = Encoding.UTF8.GetBytes(path);
  148. pMrl = Marshal.AllocHGlobal(bytes.Length + 1);
  149. Marshal.Copy(bytes, 0, pMrl, bytes.Length);
  150. Marshal.WriteByte(pMrl, bytes.Length, 0);
  151. return libvlc_video_take_snapshot(libvlc_mediaplayer, num, pMrl, width, height);
  152. }
  153. finally
  154. {
  155. if (pMrl != IntPtr.Zero)
  156. {
  157. Marshal.FreeHGlobal(pMrl);
  158. }
  159. }
  160. }
  161. public static IntPtr libvlc_media_new_location(IntPtr libvlc_instance, string path)
  162. {
  163. IntPtr pMrl = IntPtr.Zero;
  164. try
  165. {
  166. byte[] bytes = Encoding.UTF8.GetBytes(path);
  167. pMrl = Marshal.AllocHGlobal(bytes.Length + 1);
  168. Marshal.Copy(bytes, 0, pMrl, bytes.Length);
  169. Marshal.WriteByte(pMrl, bytes.Length, 0);
  170. return libvlc_media_new_path(libvlc_instance, pMrl);
  171. }
  172. finally
  173. {
  174. if (pMrl != IntPtr.Zero)
  175. {
  176. Marshal.FreeHGlobal(pMrl);
  177. }
  178. }
  179. }
  180. #endregion
  181. }
复制代码

VLCPlayer

  1. public class VLCPlayer
  2. {
  3. private IntPtr libvlc_instance_;
  4. private IntPtr libvlc_media_player_;
  5. private double duration_;
  6. public VLCPlayer(string pluginPath, bool is_record)
  7. {
  8. if (is_record == true)
  9. {
  10. string plugin_arg = "--plugin-path=" + pluginPath;
  11. string filename = "c:\" + DateTime.Now.ToString("yyyyMMddhhmmss") + ".mp4";
  12. string record_paramter = "--sout=#duplicate{dst=display,dst=std{accs=file,mux=ts,dst=" + filename;
  13. string[] arguments = { "-I", "--fullscreen", "dummy", "--ignore-config", "--no-video-title", "--width=100", "--height=100", plugin_arg, record_paramter };// "--sout=#duplicate{dst=display,dst=std{accs=file,mux=ts,dst=c:\\1.mp4" };
  14. libvlc_instance_ = LIBVLCAPI.libvlc_new(arguments);
  15. libvlc_media_player_ = LIBVLCAPI.libvlc_media_player_new(libvlc_instance_);
  16. }
  17. else
  18. {
  19. string plugin_arg = "--plugin-path=" + pluginPath;
  20. string[] arguments = { "-I", "--fullscreen", "dummy", "--ignore-config", "--no-video-title", plugin_arg };
  21. libvlc_instance_ = LIBVLCAPI.libvlc_new(arguments);
  22. libvlc_media_player_ = LIBVLCAPI.libvlc_media_player_new(libvlc_instance_);
  23. //float f1=0.1f;
  24. //LIBVLCAPI.libvlc_video_set_scale(libvlc_media_player_,f1);
  25. }
  26. }
  27. public void Vlc_release()
  28. {
  29. if (libvlc_instance_ != IntPtr.Zero)
  30. LIBVLCAPI.libvlc_release(libvlc_instance_);
  31. // if (libvlc_media_player_ != IntPtr.Zero)
  32. // LIBVLCAPI.libvlc_media_release(libvlc_media_player_);
  33. }
  34. public void SetRenderWindow(int wndHandle)
  35. {
  36. if (libvlc_instance_ != IntPtr.Zero && wndHandle != 0)
  37. {
  38. LIBVLCAPI.libvlc_media_player_set_hwnd(libvlc_media_player_, wndHandle);
  39. }
  40. }
  41. public void PlayFile(string filePath)
  42. {
  43. IntPtr libvlc_media = LIBVLCAPI.libvlc_media_new_path(libvlc_instance_, filePath);
  44. if (libvlc_media != IntPtr.Zero)
  45. {
  46. LIBVLCAPI.libvlc_media_parse(libvlc_media);
  47. duration_ = LIBVLCAPI.libvlc_media_get_duration(libvlc_media) / 1000.0;
  48. LIBVLCAPI.libvlc_media_player_set_media(libvlc_media_player_, libvlc_media);
  49. LIBVLCAPI.libvlc_media_release(libvlc_media);
  50. LIBVLCAPI.libvlc_media_player_play(libvlc_media_player_);
  51. }
  52. }
  53. public void PlayFile_rtsp(string filePath)//libvlc_media_new_location
  54. {
  55. IntPtr libvlc_media = LIBVLCAPI.libvlc_media_new_location(libvlc_instance_, filePath);
  56. if (libvlc_media != IntPtr.Zero)
  57. {
  58. // LIBVLCAPI.libvlc_media_parse(libvlc_media);
  59. // duration_ = LIBVLCAPI.libvlc_media_get_duration(libvlc_media) / 1000.0;
  60. LIBVLCAPI.libvlc_media_player_set_media(libvlc_media_player_, libvlc_media);
  61. LIBVLCAPI.libvlc_media_release(libvlc_media);
  62. LIBVLCAPI.libvlc_media_player_play(libvlc_media_player_);
  63. }
  64. }
  65. public void Pause()
  66. {
  67. if (libvlc_media_player_ != IntPtr.Zero)
  68. {
  69. LIBVLCAPI.libvlc_media_player_pause(libvlc_media_player_);
  70. }
  71. }
  72. public void take_snapshot()
  73. {
  74. if (libvlc_media_player_ != IntPtr.Zero)
  75. {
  76. string filepath = "c:\";
  77. LIBVLCAPI.libvlc_video_take_snapshot(libvlc_media_player_, 0, filepath, 0, 0);
  78. }
  79. }
  80. public void full_screen()
  81. {
  82. if (libvlc_media_player_ != IntPtr.Zero)
  83. {
  84. LIBVLCAPI.libvlc_set_fullscreen(libvlc_media_player_, 0);
  85. }
  86. }
  87. public void Stop()
  88. {
  89. if (libvlc_media_player_ != IntPtr.Zero)
  90. {
  91. LIBVLCAPI.libvlc_media_player_stop(libvlc_media_player_);
  92. }
  93. }
  94. public double GetPlayTime()
  95. {
  96. return LIBVLCAPI.libvlc_media_player_get_time(libvlc_media_player_) / 1000.0;
  97. }
  98. public void SetPlayTime(double seekTime)
  99. {
  100. LIBVLCAPI.libvlc_media_player_set_time(libvlc_media_player_, (Int64)(seekTime * 1000));
  101. }
  102. public int GetVolume()
  103. {
  104. return LIBVLCAPI.libvlc_audio_get_volume(libvlc_media_player_);
  105. }
  106. public void SetVolume(int volume)
  107. {
  108. LIBVLCAPI.libvlc_audio_set_volume(libvlc_media_player_, volume);
  109. }
  110. public void SetFullScreen(bool istrue)
  111. {
  112. LIBVLCAPI.libvlc_set_fullscreen(libvlc_media_player_, istrue ? 1 : 0);
  113. }
  114. public double Duration()
  115. {
  116. return duration_;
  117. }
  118. public string Version()
  119. {
  120. return LIBVLCAPI.libvlc_get_version();
  121. }
  122. }
复制代码

1.2static 声明 m_instance 优化服从

如下:

  1. #pragma once
  2. #include <memory>
  3. #include <basetsd.h>
  4. typedef SSIZE_T ssize_t;
  5. #include "vlc/vlc.h"
  6. #include <mutex>
  7. struct libvlc_media_track_info_t;
  8. struct libvlc_media_t;
  9. struct libvlc_instance_t;
  10. struct libvlc_media_player_t;
  11. struct libvlc_event_t;
  12. class context;
  13. enum MediaState {
  14. NothingSpecial = 0,
  15. Opening = 1,
  16. Buffering = 2,
  17. Playing = 3,
  18. Paused = 4,
  19. Stopped = 5,
  20. Ended = 6,
  21. Error = 7
  22. };
  23. class TestVlcVideo
  24. {
  25. public:
  26. TestVlcVideo();
  27. void init( std::function<void(int)> eventCallback);
  28. void setHwnd(const int64_t iHwnd) ;
  29. bool loadMedia(const char* &url) ;
  30. int play() ;
  31. void pause() ;
  32. void stop() ;
  33. void setRatio(const char* &ratio) ;
  34. int getVolume() ;
  35. int setVolume(const int volume) ;
  36. int getMediaState() ;
  37. libvlc_instance_t * getVlcInstance();
  38. libvlc_media_player_t * getVlcMediaPlayer();
  39. private:
  40. static void vlcEvents(const libvlc_event_t *ev, void *param);
  41. static libvlc_instance_t *m_instance;
  42. libvlc_media_player_t *m_mediaPlayer = nullptr;
  43. int64_t m_durationMS;
  44. std::function<void(int)> m_eventCallback;
  45. MediaState m_currentMediaState;
  46. };
复制代码

上面 static 声明的 m_instance 是为了优化服从 ,不必每次播放视频的时间 都新建。

这是第二步工作。

1.3封装 DLL

必要 封装真正的 DLL 了,向C#暴露的也是这个类内里 的方法。

  1. #pragma once
  2. typedef int(*CallBackMediaState)(int);
  3. #ifdef DLLVLC_EXPORTS // 用来导出函数
  4. #define DLLVLC_API __declspec(dllexport)
  5. #else // 用来标识为导入函数,对于引用该头文件的外部模块来说dllimport这个标记对编译优化有作用
  6. #define DLLVLC_API __declspec(dllimport)
  7. #endif#include "Testvlcvideo.h"
  8. namespace TestVLCDLL {
  9. extern "C" {
  10. /*
  11. * @brief VLC Instance和Player实例初始化
  12. * @param CallBackMediaState callback 回调函数为媒体播放状态
  13. * @return 每次vlcInit会返回一个VLC的Player ID,此ID唯一,后面的接口都需要此ID找到对应的Player
  14. */
  15. DLLVLC_API int vlcInit(CallBackMediaState callback);
  16. /*
  17. * @brief VLC 媒体加载接口
  18. * @param int index PlayerID
  19. * @param const char *path 媒体路径
  20. */
  21. DLLVLC_API bool vlcLoad(int index, const char *path);
  22. /*
  23. * @brief 设置句柄,如不设置则为默认窗口播放
  24. * @param const int64_t iHwnd windows窗口句柄
  25. */
  26. DLLVLC_API bool vlcSetHwnd(int index,const int64_t iHwnd);
  27. DLLVLC_API bool play(int index);
  28. DLLVLC_API bool pause(int index);
  29. DLLVLC_API bool stop(int index);
  30. /*
  31. * @brief 设置播放窗口比例
  32. * @param 形如 16:9 4:3 等字符串
  33. */
  34. DLLVLC_API bool setRatio(int index,const char* ratio);
  35. /*
  36. * @brief 设置媒体播放音量
  37. */
  38. DLLVLC_API bool setVolume(int index, int volume);
  39. /*
  40. * @brief 获取媒体总时长
  41. */
  42. DLLVLC_API int64_t getMediaLength(int index);
  43. /*
  44. * @brief 获取当前播放状态
  45. */
  46. DLLVLC_API int getMediaState(int index);
  47. /*
  48. * @brief 销毁VLC Player
  49. */
  50. DLLVLC_API bool vlcDisponse(int index);
  51. }
  52. }
复制代码

起首 在最开始定义了

  1. CallBackMediaState
复制代码
回调函数,对应C++ 层利用 函数指针和
  1. std::function
复制代码
都可以。然后利用
  1. DLLVLC_EXPORTS
复制代码
指示本类为导出类,然后再利用
  1. DLLVLC_API
复制代码
宏定义导出函数,这些方法都是
  1. dll
复制代码
暴露给外部调用的方法。

1.4应用程序的导出函数

  1. // DLLVLC.cpp : 定义 DLL 应用程序的导出函数。
  2. #define DLLVLC_EXPORTS
  3. #include "DLLVLC.h"
  4. #include "Testvlcvideo.h"
  5. #include <iostream>
  6. #include <map>
  7. #include <mutex>
  8. #include <atomic>
  9. std::map<int, TestVlcVideo*> g_mapVLC;
  10. std::atomic_int g_iIndex = 0;
  11. std::mutex g_mt;
  12. DLLVLC_API int TestVLCDLL::vlcInit(CallBackMediaState callback)
  13. {
  14. //如果是初次调用,则初始化instance,否则复用instance
  15. std::lock_guard<std::mutex> l(g_mt);
  16. ++g_iIndex;
  17. TestVlcVideo *vlcVideo = new TestVlcVideo;
  18. g_mapVLC.emplace(g_iIndex, vlcVideo);
  19. g_mapVLC.at(g_iIndex)->init(callback);
  20. return g_iIndex;
  21. }
  22. DLLVLC_API bool TestVLCDLL::play(int index)
  23. {
  24. std::lock_guard<std::mutex> l(g_mt);
  25. TestVlcVideo *vlcVideo = g_mapVLC.at(index);
  26. if (nullptr == vlcVideo)
  27. {
  28. return false;
  29. }
  30. vlcVideo->play();
  31. return true;
  32. }
  33. .......
复制代码


由于 我们采用的是导出接口方法,而不是导出类(导出类比较贫苦 ,本身 测试未能成功),因此在制作 dll 库时,利用 静态 map 保存干系 实例,利用 对应的 init方法和 dispose 方法借助 id 参数创建和烧毁 对象。

1.5 vlc 简单封装的具体 实现

下来再看下我们第一段代码的 cpp 文件,就是 vlc 简单封装的具体 实现:

  1. #include "Testvlcvideo.h"
  2. #include <iostream>
  3. libvlc_instance_t *TestVlcVideo::m_instance = nullptr;
  4. TestVlcVideo::TestVlcVideo()
  5. : m_mediaPlayer(nullptr)
  6. , m_durationMS(0)
  7. , m_eventCallback(nullptr)
  8. {
  9. }
  10. void TestVlcVideo::init(std::function<void(int)> eventCallback)
  11. {
  12. getVlcInstance();
  13. {
  14. getVlcMediaPlayer();
  15. libvlc_event_manager_t *em = libvlc_media_player_event_manager(m_mediaPlayer);
  16. {
  17. libvlc_event_attach(em, libvlc_MediaPlayerPlaying, vlcEvents, this);
  18. libvlc_event_attach(em, libvlc_MediaPlayerPaused, vlcEvents, this);
  19. libvlc_event_attach(em, libvlc_MediaPlayerStopped, vlcEvents, this);
  20. libvlc_event_attach(em, libvlc_MediaPlayerNothingSpecial, vlcEvents, this);
  21. libvlc_event_attach(em, libvlc_MediaPlayerOpening, vlcEvents, this);
  22. libvlc_event_attach(em, libvlc_MediaPlayerBuffering, vlcEvents, this);
  23. libvlc_event_attach(em, libvlc_MediaPlayerEndReached, vlcEvents, this);
  24. libvlc_event_attach(em, libvlc_MediaPlayerPositionChanged, vlcEvents, this);
  25. }
  26. m_eventCallback = std::move(eventCallback);
  27. }
  28. }
  29. void TestVlcVideo::setHwnd(const int64_t iHwnd)
  30. {
  31. libvlc_media_player_set_hwnd(m_mediaPlayer, (void *)iHwnd);
  32. }
  33. bool TestVlcVideo::loadMedia(const char* &url)
  34. {
  35. libvlc_media_t *m_media = nullptr;
  36. std::string url_ = url;
  37. if (url_.find("://") == std::string::npos)
  38. {
  39. m_media = libvlc_media_new_path(getVlcInstance (), url);
  40. }
  41. else
  42. {
  43. m_media = libvlc_media_new_location(getVlcInstance(), url);
  44. }
  45. if (nullptr == m_media)
  46. {
  47. m_currentMediaState = MediaState::Error;
  48. return false;
  49. }
  50. libvlc_media_player_set_media(getVlcMediaPlayer (), m_media);
  51. libvlc_media_parse(m_media);
  52. m_durationMS = libvlc_media_get_duration(m_media);
  53. libvlc_media_release(m_media);
  54. return true;
  55. }
  56. libvlc_instance_t * TestVlcVideo::getVlcInstance()
  57. {
  58. if (nullptr == m_instance)
  59. {
  60. m_instance = libvlc_new(0, NULL);
  61. }
  62. return m_instance;
  63. }
  64. libvlc_media_player_t * TestVlcVideo::getVlcMediaPlayer()
  65. {
  66. if (nullptr == m_mediaPlayer)
  67. {
  68. m_mediaPlayer = libvlc_media_player_new(m_instance);
  69. }
  70. return m_mediaPlayer;
  71. }
  72. int TestVlcVideo::play()
  73. {
  74. return libvlc_media_player_play(m_mediaPlayer);
  75. }
  76. void TestVlcVideo::pause()
  77. {
  78. if(libvlc_media_player_is_playing(m_mediaPlayer))
  79. {
  80. libvlc_media_player_set_pause(m_mediaPlayer, 1);
  81. }
  82. else
  83. {
  84. libvlc_media_player_set_pause(m_mediaPlayer, 0);
  85. }
  86. }
复制代码

到这儿,一样平常 环境 下我们还必要 设置

  1. def
复制代码
文件,以避免导出的函数名被增长 额外的信息,而不是简短的“
  1. play
复制代码
”等。但是可以看到我们在全部 的导出函数前增长 了“
  1. extern C
复制代码
”标识。意思是这些函数按照
  1. C
复制代码
标准举行 编译,由于C++ 的函数重载,再加上各个编译器的不同,导致编译而出的函数名被(
  1. mangled name
复制代码
),且各不类似 ,但是C不支持重载,因此采用同一 的编译规定,同时也可以保证此函数被
  1. C
复制代码
准确 调用,以是 我们就无需写
  1. def
复制代码
文件也可以保证函数名不被粉碎 。

2、C# 调用

上面简要说完了 C++ 端关于 DLL 的封装,再总结一下大概就是这几点:

  • 至少必要 两个文件,一个是本身 对具体 实现的封装类,一个是导出方法文件,本文中我们没有利用 类,而是直接导出函数。
  • 回调函数像如许 typedef int(*CallBackMediaState)(int); 去定义。
  • 导出文件添加宏 dllexport
  1. #ifdef DLLVLC_EXPORTS // 用来导出函数
  2. #define DLLVLC_API __declspec(dllexport)
  3. #else // 用来标识为导入函数,对于引用该头文件的外部模块来说dllimport这个标记对编译优化有作用
  4. #define DLLVLC_API __declspec(dllimport)
  5. #endif
复制代码

导出函数添加 extern "C" DLLVLC_API 声明。

2.1C# 回调函数声明与定义

  1. [DllImport(@"C:\Users\HiWin10\Desktop\DLLVLC\DLLVLC\DLLVLC\x64\Release\DLLVLC.dll", EntryPoint = "vlcInit",
  2. SetLastError = true,
  3. CharSet = CharSet.Ansi,
  4. ExactSpelling = false,
  5. CallingConvention = CallingConvention.Cdecl)]
  6. public extern static int vlcInit(DllcallBack pfun);
  7. [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
  8. public delegate int DllcallBack(int MediaState);
复制代码

C# 的回调函数即为委托,必要 提前定义委托 DllcallBack ,然后我们假定它是被 C++ 承认 的,作为参数传入 vlcInit。在下面我们必要 写此委托函数具体 的实现:

  1. public static int CsharpCall(int MediaState)
  2. {
  3. Console.WriteLine(MediaState);
  4. return MediaState;
  5. }
复制代码

利用 的时间 :

  1. static int index;
  2. static void Main(string[] args)
  3. {
  4. DllcallBack mycall;
  5. mycall = new DllcallBack(Program.CsharpCall);
  6. index = vlcInit(mycall);
  7. ......
  8. }
复制代码

颠末 验证,此种方式的回调函数能被 C++ 承认,对应于C++的 std::function。

2.2C# 导出平常 函数调用

  1. [DllImport(@"C:\Users\HiWin10\Desktop\DLLVLC\DLLVLC\DLLVLC\x64\Release\DLLVLC.dll", EntryPoint = "vlcLoad",
  2. CallingConvention = CallingConvention.Cdecl)]
  3. public extern static bool vlcLoad(int index, string path);
  4. [DllImport(@"C:\Users\HiWin10\Desktop\DLLVLC\DLLVLC\DLLVLC\x64\Release\DLLVLC.dll", EntryPoint = "vlcSetHwnd",
  5. CallingConvention = CallingConvention.Cdecl)]
  6. public extern static bool vlcSetHwnd(int index, int iHwnd);
复制代码

上面是 C# 关于平常 导出函数的加载方法,在 main 函数中直接举行 调用即可。

  1. static int index;
  2. static void Main(string[] args)
  3. {
  4. DllcallBack mycall;
  5. mycall = new DllcallBack(Program.CsharpCall);
  6. index = vlcInit(mycall);
  7. Console.WriteLine(vlcLoad(index, @"D:\1.mp4"));
  8. Console.WriteLine(getMediaLength(index));
  9. play(index);
  10. setRatio(index,"16:9");
复制代码

实在

  1. C#
复制代码
端的调用还是比较简单的,上面的方式是采用静态加载的方式,必要 将C++ 的
  1. dll
复制代码
放到 C# 工程
  1. bin
复制代码
目次 下,而动态加载的方式笔者未举行 尝试。

整个过程就完成了,利用 C++ 封装的方式可以利用 一些只支持 C++,只有 C++ API 的强盛 库,也可以防止反编译,还可以使代码更好的分层等。

下面附上demo链接,有必要 的小伙伴可下载运行(VS2015)

DLLVLCfor_jb51.rar

到此这篇关于C++ 封装 DLL 供 C# 调用具体 先容 的文章就先容 到这了,更多干系 C++ 封装 DLL 供 C# 调用内容请搜索 脚本之家从前 的文章或继续欣赏 下面的干系 文章渴望 大家以后多多支持脚本之家!


免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!
回复

使用道具 举报

avatar 莫言941 | 2021-9-14 18:21:16 | 显示全部楼层
在这个版块混了这么久了,第一次看见这么给你的帖子!
回复

使用道具 举报

avatar 加菲猫419 | 2021-9-21 09:17:19 | 显示全部楼层
admin楼主很有激情啊!
回复

使用道具 举报

avatar 彭832 | 2021-10-3 01:17:12 | 显示全部楼层
admin楼主,您主治大夫在到处找您呢!
回复

使用道具 举报

avatar 水果甜蜜蜜潮 | 2021-10-3 08:37:38 | 显示全部楼层
今天是个特别的日子,值得纪念!
回复

使用道具 举报

avatar 晴朗71 | 2021-10-3 08:50:12 | 显示全部楼层
东方不败外加灭绝师太啊!
回复

使用道具 举报

avatar 马宝清马宝清 | 2021-10-4 00:33:19 | 显示全部楼层
帖子好乱!
回复

使用道具 举报

avatar 普通人物怨 | 2021-10-15 22:56:10 | 显示全部楼层
态度决定一切,不错!
回复

使用道具 举报

avatar 漠河龙哥 | 昨天 07:18 | 显示全部楼层
脑残片admin楼主今天吃了么?
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则