I'm writing a super-simple ultra-lite weight .Net wrapper for the LibVLC media library since the only things I need access to are the ability to play, pause and stop media files. I've posted a couple of questions on this and gotten some answers but unfortunately I'm just left with more questions.

We'll start from the top and work down.

The documentation first states I have to initialize VLC with a call to the function with this specification:

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

for which I have the defined the following method:

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

And I'm calling the function like this:

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

I have tried it several different ways. Initially I did not know about the CallingConvention which was leading to an unbalanced stack which brought me here in the first place. That issue was resolved and the method has gone through several iterations, none of which have proved successful, by which I mean IntPtr is always 0 after the method call. I've tried it like it is above, with the second argument being String[] argc, [MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.LPStr)] string[], I've tried having it return to a Long (which actually resulted in the Long having a value in it), but nothing so far has worked correctly.

Does anyone know the correct way to call this function from the LibVLC DLL Library?

EDIT: On a suggestion I tried calling the error message function of the library:

Specification:

const char* libvlc_errmsg (void)

Implementation:

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

Call:

Console.WriteLine(DGLibVLC.GetLastError());

Result:

Null

The documentation states it will return Null if there is no error. This must indicate that the initial function call NewCore was working correctly but something is still going wrong somehow.

To be cover all bases I checked that the DLLs match the documentation, they do. 2.0.6.0. The documentation I am referencing is here.

EDIT: I can confirm there is no error. When using an initialized to zero long variable to store the result of NewCore I can see it returning something. What I am doing wrong here is where I am trying to store the pointer being returned by the unmanaged function that returns the pointer to the object. How do I store the pointer to the opaque structure reference being passed back?

有帮助吗?

解决方案 2

So after much looking around and asking questions I've come full circle. I looked deeply into LibVLC.Net and found how they were importing the DLL functions and adapted what they did to my own wrapper and it worked.

To summarize:

There are some Win32 API functions declared in the code at the start:

    [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);

that handle providing a handle to a dll and setting a directory search path.

I don't know exactly what it all means but when you initialize the LibVLC.Net library (the primary object) it loads pretty much EVERY function like so:

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

That delegate is defined here like so:

[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);
}

And it has a public function that calls the delegate once defined.

I simply stripped down the function that defines the library instance and imported only the functionality I needed.

Thanks very much to everyone who was so patient in helping me along. I likely wouldn't have been able to come to a solution without your help.

EDIT: Okay so it wasn't that. It was the location of the LibVLC Plugin Directory. So it was something stupid -.-;

其他提示

It doesn't have anything to do with the way you call the function. You cannot get anywhere when you get IntPtr.Zero back from libvlc_new(). It means "there was an error". You'll need to focus on error reporting first, call libvlc_errmsg() to try to get a description for the problem.

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top