当我尝试将路径传递给文件名时,我有一个非托管函数调用抛出此异常。
我已经读过这可能是由DLL本身引起的,但我不认为是这种情况,因为DLL在另一个应用程序中使用,所以问题很可能在我调用该函数的方法中。
规范:
libvlc_media_new_path (libvlc_instance_t *p_instance, const char *path)
说明
p_instance the instance
path local filesystem path
我的方法:
[DllImport("libvlc", EntryPoint = "libvlc_media_new_path")]
public static extern IntPtr NewMedia(IntPtr instance,
[MarshalAs(UnmanagedType.LPStr)] string path);
我想我错过了常规电话,但这可能是什么?或者它会导致这种异常吗?
编辑:基于一些评论,我做了一些探讨,发现......好吧,没什么。该实例的结构是不透明的,这意味着我不知道Laymans术语。我的猜测是,这意味着您不需要在使用它的应用程序中重建它?在基于this的盲目猜测中,我将我一直使用的返回值替换为负责将* p_instance值设置为long
而不是IntPtr
的函数。因为当它是IntPtr
时它返回0,并且很长时间我看到了一个值。再一次,IntPtr
我真的不知道。我很高兴在实例变量中看到不是0的东西,但是当我将它运行过去时,它再次出错了。
编辑:我已将问题扩展为here。
答案 0 :(得分:1)
根据您所看到的例外以及您为本机功能提供的声明,
libvlc_media_new_path (libvlc_instance_t *p_instance, const char *path)
你的p / invoke声明不正确。你的调用约定不匹配。 .NET p / invoke系统的默认设置是stdcall(以匹配Windows API函数),但C和C ++代码的默认值是cdecl。您必须明确告诉.NET您的函数使用cdecl调用约定。
所以改成它看起来像这样:
[DllImport("libvlc", EntryPoint = "libvlc_media_new_path", CallingConvention = CallingConvention.Cdecl)]
public static extern IntPtr NewMedia(IntPtr instance,
[MarshalAs(UnmanagedType.LPStr)] string path);
当然,我猜你的回归值是指针是正确的。您显示的本机函数声明缺少返回类型。
关于instance
参数的问题,以及您是否正确使用IntPtr
类型:参数是指向libvlc_instance_t
的指针,因此您有两种基本方法:使用p / invoke进行工作。首先是将参数声明为IntPtr
,使其像原始指针值一样进行编组。这对于指针需要不透明(即从一个本机函数检索,存储,然后传递给另一个本机函数)的情况不是特别有用。其次是声明一个镜像本机结构的托管结构,然后编写p / invoke声明来使用这个结构,以便编组器自动处理事物。如果您确实需要与存储在指针所指向的结构中的值进行交互,那么这将非常有用。
在这种情况下,在Google搜索之后,您似乎正在使用其中一个VLC API。具体来说是this one。 also tells us libvlc_instance_t
是什么:它是一个代表libvlc实例的不透明结构。因此,声明托管结构不是一种选择,因为即使本机代码也将结构视为不透明。你真正需要的只是指针,来回传递;我上面谈到的第一种方法的完美案例。所以上面显示的声明就是你的赢家。
现在唯一的战斗是获取一个指向libvlc实例的有效指针,只要你调用它就可以传递给该函数。有可能会事先调用像libvlc_new
这样的函数,它被记录为创建和初始化新的libvlc实例。它的返回值正是您所需要的。因此,除非您已经创建了一个libvlc实例(在这种情况下,使用该指针),您还需要调用此函数并存储其结果。
如果the documentation对于libvlc_new
函数的参数所需的值是正确的,您可以非常简单地声明:
[DllImport("libvlc", EntryPoint = "libvlc_new", CallingConvention = CallingConvention.Cdecl)]
public static extern IntPtr NewCore(int argc, IntPtr argv);
然后这样称呼它:
IntPtr pLibVlc = NewCore(0, IntPtr.Zero);
// now pLibVlc should be non-zero
当然,我对VLC API一无所知,但是我对API设计的一般知识告诉我,一旦你完成,你可能需要用一个实例的同一个指针来调用libvlc_release
函数用它。
答案 1 :(得分:0)
尝试没有[MarshalAs(UnmanagedType.LPStr)],通常适合我。