当我尝试将路径传递给文件名时,我有一个非托管函数调用抛出此异常 .
我已经读过这可能是由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,并且有一个长的我看到了一个 Value . 再一次,我真的不知道 IntPtr
. 我很高兴在实例变量中看到不是0的东西但是当我跑过它时,它再次出错了 .
编辑:我已将问题扩展到here .
2 回答
基于您所看到的异常以及您为本机函数提供的声明,
你的p / invoke声明不正确 . 你的调用约定不匹配 . .NET p / invoke系统的默认设置是stdcall(以匹配Windows API函数),但C和C代码的默认值是cdecl . 您必须明确告诉.NET您的函数使用cdecl调用约定 .
所以改成它看起来像这样:
当然,我猜你的回归值是指针是正确的 . 您显示的本机函数声明缺少返回类型 .
至于你关于
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
函数的参数所需的值是正确的,您可以非常简单地声明它:并称之为:
当然,我对VLC API一无所知,但是我对API设计的一般知识告诉我,一旦你完成它,你可能需要使用相同的指针来调用libvlc_release函数 .
尝试没有[MarshalAs(UnmanagedType.LPStr)],通常适合我 .