libvlc_new always return null in vlc 2.1.3 - c#

libvlc_new always return null. I have copied libvlc.dll and libvlccore.dll in debug folder of my solution directory.
We have also tried calling libvlc_new(0,null) and set the environment variable "VLC_PLUGIN_PATH " to plugins directory, with same result.
Any pointer what is going wrong/ or what is the best way to access libVlc API programmitically in .net environment.
PLEASE FIND CODE SNIPPET BELOW deveopled in C#, VS2010.
IntPtr instance, player ;
string[] args = new string[] {
"-I", "dummy", "--ignore-config",
#"--plugin-path=D:\plugins",
"--vout-filter=deinterlace", "--deinterlace-mode=blend"
};
instance = LibVlc.libvlc_new(args.length, args);
IntPtr media = LibVlc.libvlc_media_new_location(instance, #"rtsp://username assword#IP_address/path");
player = LibVlc.libvlc_media_player_new_from_media(media);
LibVlc.libvlc_media_player_set_hwnd(player, panel1.Handle);
LibVlc.libvlc_media_player_play(player);
we have done P/Invoke for corresponding library calls as:
[DllImport("D:\\myvlc\\myvlc\\bin\\Debug\\libvlc", CallingConvention = CallingConvention.Cdecl)]
public static extern IntPtr libvlc_new(int argc, [MarshalAs(UnmanagedType.LPArray,
ArraySubType = UnmanagedType.LPStr)] string[] argv);
[DllImport("D:\\myvlc\\myvlc\\bin\\Debug\\libvlc", CallingConvention = CallingConvention.Cdecl)]
public static extern IntPtr libvlc_media_new_location(IntPtr p_instance,
[MarshalAs(UnmanagedType.LPStr)] string psz_mrl);
[DllImport("D:\\myvlc\\myvlc\\bin\\Debug\\libvlc", CallingConvention = CallingConvention.Cdecl)]
public static extern IntPtr libvlc_media_player_new_from_media(IntPtr media);
[DllImport("D:\\myvlc\\myvlc\\bin\\Debug\\libvlc", CallingConvention = CallingConvention.Cdecl)]
public static extern void libvlc_media_player_set_hwnd(IntPtr player, IntPtr drawable);
[DllImport("D:\\myvlc\\myvlc\\bin\\Debug\\libvlc", CallingConvention = CallingConvention.Cdecl)]
public static extern void libvlc_media_player_play(IntPtr player);

The param --plugin-path" was ignored.
By copying the whole plugin directory works with 2.1.3.

Found solution, all you need to do is to copy plugins folder to the debug directory of your visual studio solution folder. Hope this would save some time for others trying the same thing. I have been trying this for almost 1 day.

Related

Using QPDF with C#

I am attempting to translate this qpdf command:
qpdf --qdf --object-streams=disable input.pdf editable.pdf
into the equivalent method calls I would need when using the qpdf dll (available from here: https://sourceforge.net/projects/qpdf/).
I ran the qpdf dll through dumpbin to get the function names, and by looking at the header files that were included for use with a c++ project I can see the parameters for the functions.
For example the function needed to impart the --object-streams option above would (from what I can tell) be this function:
void setObjectStreamMode(qpdf_object_stream_e);
from the c++ header file which becomes:
[DllImport("qpdf21.dll")]
static extern void _ZN10QPDFWriter19setObjectStreamModeE20qpdf_object_stream_e(int stateEnum);
in the C# file.
The problem is when I use the above function I get an
AccessViolationException: Attempted to read or write protected memory
error, which makes me think I need to create a QPDF object somehow, but I have never used object oriented pinvokes, so I'm at a loss of how to make the object accessible in c#.
If anyone is already familiar with using the dll in C#, or even in C++, and could tell me the correct functions to call to replicate the command I would appreciate it!
I've managed to figure it out, the below code replicates the command, turns out I was looking into the wrong header file:
[DllImport("qpdf21.dll", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
static extern IntPtr qpdf_init();
[DllImport("qpdf21.dll", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
static extern void qpdf_cleanup(ref IntPtr qpdfData);
[DllImport("qpdf21.dll", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
static extern int qpdf_read(IntPtr qpdfdata, [MarshalAs(UnmanagedType.LPStr)] string fileName, IntPtr password);
[DllImport("qpdf21.dll", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
static extern void qpdf_set_object_stream_mode(IntPtr qpdf, int mode);
[DllImport("qpdf21.dll", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
static extern void qpdf_set_qdf_mode(IntPtr qpdf, int value);
[DllImport("qpdf21.dll", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
static extern int qpdf_init_write(IntPtr qpdf, [MarshalAs(UnmanagedType.LPStr)] string fileName);
[DllImport("qpdf21.dll", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
static extern int qpdf_write(IntPtr qpdf);
static void Main(string[] args)
{
//call init
IntPtr qpdfData = qpdf_init();
//call read (which gets and processes the input file)
//0 result == good
int result = qpdf_read(qpdfData, #"scan.pdf", IntPtr.Zero);
//call init_write
result = qpdf_init_write(qpdfData, #"scanEditable.pdf");
//set write options
//disable object stream mode
qpdf_set_qdf_mode(qpdfData, 1);
qpdf_set_object_stream_mode(qpdfData, 0);
//call write
result = qpdf_write(qpdfData);
//call cleanup
qpdf_cleanup(ref qpdfData);
}
Looks like you've figured out a good answer here. You've discovered the C API, which is intended for helping to use QPDF from languages other than C++ through the DLL. The C API is primarily documented in the qpdf-c.h header file. You can find some information in the Using Other Languages section of the manual as well. The C API does not expose the full functionality of qpdf's C++ library. If you find missing pieces, please feel free to create an issue at github. I try to update the C API when I add new interfaces, but I don't do it for every interface, and some of the functionality in the CLI is implemented directly in the tool and doesn't map to a single library function.
If the C API is not rich enough for your use case, it's also possible to write your own C++ class with some functions declared extern "C", export them, and build an additional DLL that you can use in the manner you have found above. You can look at qpdf-c.cc as an example of how this works.

View a type within a dll to use in a function used by that Dll

I've got a COM interface dll, and some documentation about the methods within the dll, however from what I can tell with the documentation, the method requires a custom struct be passed in as an out parameter, but the documentation doesn't provide any information about the struct itself.
The function I'm calling from c# is as follows:
API
UINT OpenRequest ([out] PHCOMS phComs,
[in] PCHAR pEndPointName,
[in] UINT fBlockingMode,
[in] UINT fOpenMode,
[in] UINT fDataType,
[in] HINSTANCE hInstance)
My issue is that PHCOMS is a type described in the documentation as:
The address of a variable of type HCOMS. The communications handle to be used by the other API calls, is returned in this variable. If an error occurs this will be NULL.
This function starts by allocating a comms handle (hComs), if
available, to the application. This handle is used for creating a new
connection object. The parameters of this function are assigned to the
relevant members. For this object, a pointer instance is created for
connecting to the interface, as well as the PC Headerpched
interface
I've had a look at various dll inspectors and other posts on SO but can't find anything that helps with how I can actually create a struct that's going to be validly accepted by the function.
I am also unsure if I'm misinterpreting what I need to do - is it possible that I just need to pass a standard handle through to the function or something similar? Is the PHComs type a non custom type that I just can't find info on in google?
Right now I'm attempting to call the function through c# using the DLLImport attribute over an extern function which seems to be ok except that the handle I get back is never valid, which I'm blindly (I've never done something like this before) trying to do like this
[DllImport("MyDll.dll", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.StdCall)]
public static extern uint OpenRequest(ref SafeProcessHandle hComs, string host, uint fBlockingMode, uint fOpenMode, uint fDataType, SafeProcessHandle hInstance);
static void Main(string[] args)
{
IntPtr h = new IntPtr();
var handle = new SafeProcessHandle(h, true);
uint test = 0;
test = OpenRequest(ref handle, "Host01", 0, 0, 0, handle);
handle.Dispose();
}
Any assistance on how to setup my test properly would help too since I'm blindly guessing about the IntPtr and use of whatever Safe*Handle Classes.
Edit
I've changed it to be like this following Hans' comment:
As you said, there are other methods that use that handle, for example the ConnectRequest added below.
Any suggestion as to what the HInstance parameter refers to? I doubt it's correct that I'm just passing the same handle/IntPtr in again?
The documentation says:
hInstance HINSTANCE Windows programs must pass their instance handle.
[DllImport("MyDll.dll", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.StdCall)]
public static extern uint OpenRequest(out IntPtr hComs, string host, uint fBlockingMode, uint fOpenMode, uint fDataType, IntPtr hInstance);
[DllImport("MyDll.dll", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.StdCall)]
public static extern uint ConnectRequest(IntPtr hComs, uint cTimeOut);
static void Main(string[] args)
{
IntPtr hComs = new IntPtr();
uint test_OpenRequest = 0;
test_OpenRequest = OpenRequest(out hComs, "Host01", 0, 0, 0, hComs);
}
Edit 2
[DllImport("WinCom32.dll", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.StdCall)]
public static extern uint OpenRequest(out IntPtr hComs, string host, uint fBlockingMode, uint fOpenMode, uint fDataType, IntPtr hInstance);
static void Main(string[] args)
{
IntPtr hComs = new IntPtr();
uint test_Request = 0;
string hostName = ConfigurationManager.AppSettings["HostName"];
IntPtr hInstance = Marshal.GetHINSTANCE(Assembly.GetEntryAssembly().GetModules()[0]);
test_Request = OpenRequest(out hComs, hostName, 0, 0, 1, hInstance);
Console.WriteLine("Request response value: " + test_Request.ToString());
}
There's a test application I can run that shows that this is supposed to work because it's able to connect to the host, so I've got to be doing something wrong.

How to implement a .dll in unity code

I wrote a code in unity to read some data from a measurement plate. Unfortunately the compiler gives the following error out:
Assets/Scribts/Initialize.cs(74,35): error CS0246: The type or namespace name `IDevice' could not be found. Are you missing an assembly reference?
After some research I found out that unity can't work with .dll's out of .NET languages. Thus you have to put it into a native plugin.
Do you know what to do or if there are some sample projects?
Thank you for your help.
There is an entire tutorial on this you can read here: http://www.alanzucconi.com/2015/10/11/how-to-write-native-plugins-for-unity/
The summary is:
1) Put the native plugin into the Assets/Plugins folder.
2) Define the api in a class, like:
[DllImport("TestDLL", EntryPoint = "TestSort")]
public static extern void TestSort(int [] a, int length);
There's an example of sqlite here to look at here: https://github.com/codecoding/SQLite4Unity3d
You'll see the C# code is along the lines of the above:
[DllImport("sqlite3", EntryPoint = "sqlite3_open", CallingConvention=CallingConvention.Cdecl)]
public static extern Result Open ([MarshalAs(UnmanagedType.LPStr)] string filename, out IntPtr db);
[DllImport("sqlite3", EntryPoint = "sqlite3_open_v2", CallingConvention=CallingConvention.Cdecl)]
public static extern Result Open ([MarshalAs(UnmanagedType.LPStr)] string filename, out IntPtr db, int flags, IntPtr zvfs);
[DllImport("sqlite3", EntryPoint = "sqlite3_open_v2", CallingConvention = CallingConvention.Cdecl)]
public static extern Result Open(byte[] filename, out IntPtr db, int flags, IntPtr zvfs);
[DllImport("sqlite3", EntryPoint = "sqlite3_open16", CallingConvention = CallingConvention.Cdecl)]
public static extern Result Open16([MarshalAs(UnmanagedType.LPWStr)] string filename, out IntPtr db);
[DllImport("sqlite3", EntryPoint = "sqlite3_enable_load_extension", CallingConvention=CallingConvention.Cdecl)]
public static extern Result EnableLoadExtension (IntPtr db, int onoff);
...but also notice how many #ifdef conditions there are.
Building cross platform native bindings is hard work.
Also note this only applies to C/C++ libraries; if you have an existing C# .Net library (eg. NHibernate), the answer is no, you just flat out can't use that DLL; you must get the C# source and recompile it specifically for unity.

Memory access violation while passing void* param to DLL function

I'm adding new disk device to system from my C# code, so I want to call
[System.Runtime.InteropServices.DllImport("Shell32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
public extern static void SHChangeNotify(long wEventId, uint uFlags, IntPtr dwItem1, IntPtr dwItem2);
like below
MyWin32Functions.SHChangeNotify(0x00000100/*ADDRIVE*/, 0x0005/*PATHW*/, driveLetter, IntPtr.Zero);
dwItem1 is void* and we should pass a wchar_t* (pointing to null terminated string) containing drive root in this case; so driveLetter above is
string letter = "Z:\\";
byte[] data = Encoding.Default.GetBytes(letter);
byte[] zdata = new byte[data.Length + 1];
data.CopyTo(zdata, 0);
IntPtr p = System.Runtime.InteropServices.Marshal.AllocHGlobal(zdata.Length);
System.Runtime.InteropServices.Marshal.Copy(zdata, 0, p, zdata.Length);
(my code almost same as code in similiar case: How to call SHChangeNotify from C# without error 14007
but I get System.AccessViolationException)
Any suggestions what am I doing wrong?
The first parameter in your interop signature should be an int, not a long. Though the Win32 function is declared as LONG, a LONG in Win32 is 32-bit.
[System.Runtime.InteropServices.DllImport("Shell32.dll")]
public extern static void SHChangeNotify(int wEventId, uint uFlags, IntPtr dwItem1, IntPtr dwItem2);
This MSDN article shows the common mapping between Win32 types an .NET types for Platform Invoke.

Can't find SDL_LoadBMP() entry point in 'SDL.DLL' with PInvoke

I'm trying to marshal data between SDL and my C# .NET program. The first few calls that I make into SDL.DLL work fine, inasmuch as I get no error and my Windows console app does open an empty application window:
My_SDL_Funcs.SDL_Init(0x0000FFFF); // SDL_INIT_EVERYTHING
IntPtr scrn = My_SDL_Funcs.SDL_SetVideoMode(SCREEN_WIDTH, SCREEN_HEIGHT, SCREEN_BPP, 0x00000000); // SDL_SWSURFACE
screen = (SDL_Surface)Marshal.PtrToStructure(scrn, typeof(SDL_Surface));
My_SDL_Funcs.SDL_WM_SetCaption("Hello World", null);
// ...
When I try to call SDL_LoadBMP() however, I get this runtime error:
Unable to find an entry point named 'SDL_LoadBMP' in DLL 'SDL'.
The SDL doc says that SDL_LoadBMP takes a const char* file name and returns a pointer to a SDL_Surface struct.
I first tried declaring the PInvoke as:
[DllImport("SDL", CallingConvention = CallingConvention.Cdecl)]
public static extern IntPtr SDL_LoadBMP([MarshalAs(UnmanagedType.LPWStr)] string file);
When this didn't work, I tried:
public static extern IntPtr SDL_LoadBMP(IntPtr file);
and used:
IntPtr fn = Marshal.StringToHGlobalAnsi(filename);
IntPtr loadedImage = My_SDL_Funcs.SDL_LoadBMP(fn);
Assuming that that the function actuall does exist in this library (SDL.DLL version 1.2.14), am I using the wrong invocation for a const char*?
I downloaded the DLL version you are using, and could not find an export for SDL_LoadBMP.
There is a SDL_LoadBMP_RW, though, so you could rig up your own helper call like so:
private const string SDL = "SDL.dll";
[DllImport(SDL, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
public static extern IntPtr SDL_LoadBMP_RW(IntPtr src, int freesrc);
[DllImport(SDL, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
public static extern IntPtr SDL_RWFromFile(string file, string mode);
public static IntPtr SDL_LoadBMP(string file)
{
return SDL_LoadBMP_RW(SDL_RWFromFile(file, "rb"), 1);
}
UPDATE:
I had a look through the code, and the call you are looking for is defined as a macro, so that is why you can't call it directly. Using the above code basically does the same thing as the macro defintion:
#define SDL_LoadBMP(file) SDL_LoadBMP_RW(SDL_RWFromFile(file, "rb"), 1)

Categories