1

我正在为 LibVLC 媒体库编写一个超级简单的超轻量级 .Net 包装器,因为我唯一需要访问的是播放、暂停和停止媒体文件的能力。我已经就此发布了几个问题并得到了一些答案,但不幸的是我还有更多问题。

我们将从顶部开始向下工作。

文档首先说明我必须使用此规范调用函数来初始化 VLC:

libvlc_instance_t* libvlc_new (int argc, const char *const *argv)

我为此定义了以下方法:

[DllImport("libvlc", EntryPoint = "libvlc_new", 
CallingConvention = CallingConvention.Cdecl)]
public static extern IntPtr NewCore(int argc, IntPtr argv);

我正在调用这样的函数:

private IntPtr Instance;
this.Instance = DGLibVLC.NewCore(0, IntPtr.Zero);

我已经尝试了几种不同的方法。最初我不知道 CallingConvention 会导致堆栈不平衡,这首先将我带到了这里。该问题已解决,并且该方法经过了多次迭代,但没有一次证明是成功的,我的意思是 IntPtr 在方法调用后始终为 0。我已经像上面那样尝试过,第二个参数是String[] argc, [MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.LPStr)] string[],我尝试让它返回一个 Long (这实际上导致 Long 在其中有一个值),但到目前为止没有任何工作正常。

有谁知道从 LibVLC DLL 库中调用此函数的正确方法?

编辑:根据一个建议,我尝试调用库的错误消息函数:

规格:

const char* libvlc_errmsg (void)

执行:

[DllImport("libvlc", EntryPoint = "libvlc_errmsg", 
CallingConvention = CallingConvention.Cdcel)]
public static extern string GetLastError();

称呼:

Console.WriteLine(DGLibVLC.GetLastError());

结果:

Null

文档指出,如果没有错误,它将返回 Null。这必须表明初始函数调用NewCore工作正常,但仍以某种方式出错。

为了涵盖所有基础,我检查了 DLL 是否与文档匹配,它们确实如此。2.0.6.0。我引用的文档在这里

编辑:我可以确认没有错误。当使用初始化为零的 long 变量来存储 NewCore 的结果时,我可以看到它返回了一些东西。我在这里做错的是我试图存储由返回指向对象的指针的非托管函数返回的指针。如何存储指向被传回的不透明结构引用的指针?

4

2 回答 2

1

它与您调用函数的方式没有任何关系。当您从 libvlc_new() 返回 IntPtr.Zero 时,您将无法到达任何地方。这意味着“有一个错误”。您需要首先关注错误报告,调用 libvlc_errmsg() 以尝试获取问题的描述。

于 2013-08-13T16:07:34.040 回答
1

因此,在环顾四周并提出问题后,我绕了一圈。我深入研究了 LibVLC.Net,发现他们是如何导入 DLL 函数的,并将他们所做的调整到我自己的包装器中,并且它起作用了。

总结一下:

开头的代码中声明了一些 Win32 API 函数:

    [DllImport("kernel32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
    [return: MarshalAs(UnmanagedType.Bool)]
    private static extern bool SetDllDirectory(string lpPathName);

    [DllImport("kernel32", SetLastError = true)]
    private static extern IntPtr LoadLibrary(string lpFileName);

    [DllImport("kernel32", CharSet = CharSet.Ansi, ExactSpelling = true, SetLastError = true)]
    private static extern IntPtr GetProcAddress(IntPtr hModule, string procName);

    [DllImport("kernel32.dll", SetLastError = true)]
    private static extern bool FreeLibrary(IntPtr hModule);

该句柄为 dll 提供句柄并设置目录搜索路径。

我不知道这到底是什么意思,但是当你初始化 LibVLC.Net 库(主要对象)时,它会加载几乎每个函数,如下所示:

m_libvlc_media_player_new = (libvlc_media_player_new_signature)LoadDelegate<libvlc_media_player_new_signature>("libvlc_media_player_new");

该委托在这里定义如下:

[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
private delegate IntPtr libvlc_media_player_new_signature(IntPtr p_instance);

//==========================================================================
private readonly libvlc_media_player_new_signature m_libvlc_media_player_new;

//==========================================================================
public IntPtr libvlc_media_player_new(IntPtr p_instance)
{
  VerifyAccess();

  return m_libvlc_media_player_new(p_instance);
}

它有一个公共函数,一旦定义就会调用委托。

我只是剥离了定义库实例的函数,只导入了我需要的功能。

非常感谢所有耐心地帮助我的人。如果没有您的帮助,我可能无法找到解决方案。

编辑:好的,不是那样的。它是 LibVLC 插件目录的位置。所以这是愚蠢的-.-;

于 2013-08-13T21:33:32.967 回答