Search code examples
c#.netlibrariesdesktop-application

Can I use libraries written in a different language than my program?


I'm learning .NET framework and basically I'm trying to make a desktop application that converts YouTube URLs into mp3 format. I did some research and found that my best bet would be to use the FFmpeg library. But it is not a .NET library (not written in any of the .NET languages).

So, my question is can I use a library that is written in a different language?

I was browsing through GitHub for potential solutions, and a lot of them seemed to use the FFmpeg library, and I'm wondering how that's possible (if) the libraries are written in different languages. Thanks.


Solution

  • TL;DR: Yes, or no, it depends on the type of library. I would suggest you go to nuget.org and check out the available packages that have already done all the legwork for you.


    A full answer is probably about a books worth so let me boil down to something more managable and at least things I know. Also, emphasis on things I know.

    Let's avoid focusing on C#, and instead focus on .NET, as this answer, nor the ways I will write about, are in any way specific to C#, instead they're specific to .NET.

    You can, in general, reference two types of external libraries from a .NET assembly:

    • Other .NET Assemblies
    • Windows DLLs (more about Linux a bit later)

    Referencing other .NET assemblies will use the same technology in the final assembly, a reference to it, but to get there you have several options:

    1. You can create a sibling .NET project in your same solution file, and make a project reference
    2. You can add a dependency on a Nuget package
    3. You can add a direct reference to an assembly file you have on disk

    These 3 options will all end up embedding a reference to the assembly in question. This will be just normal .NET code you reference so nothing magical happens here. You've almost certainly already done so.

    Now, for Windows DLLs, that is, .dll files that aren't .NET assemblies, you need to do something else.

    You need to use P/Invoke, which is basically the name for how to reference such DLLs and their functions.

    To use this, you would need to declare an extern method with the [DllImport(...)] attribute, as well as careful use of the right parameter types and so on. Here's an example from PInvoke.net:

    [DllImport("gdi32.dll")]
    static extern bool ArcTo(IntPtr hdc, int nLeftRect, int nTopRect,
       int nRightRect, int nBottomRect, int nXRadial1, int nYRadial1,
       int nXRadial2, int nYRadial2);
    

    Writing extern methods properly requires careful attention to the data types involved. Unless this is your only option left, I would suggest you try the nuget path instead.


    Now, ffmpeg is neither a .NET assembly nor a Windows DLL (to my knowledge), so neither of these two options are available. If the library is available in a library suitable for linking to a C++ program, then what you have to do is write a Interop Assembly, basically create .NET classes in C++ that bridge the gap over to the ffmpeg library you want to use. Since C++.NET projects can both link to such libraries and also produce a .NET assembly, this can be done, but again careful attention to involved types needs to be done.

    I would assume someone has already done this job and scouring nuget.org turned up these nuget packages:

    My suggestion would be to go check out these nuget packages. Since ffmpeg contains several different libraries with different purposes, you would need to find one that gives access to the library you're interested in.

    Finally, if you're using .NET Core, and need to do this thing on Linux, you would need to do the same thing as for Windows DLLs above, except that .NET Core on Linux can add similar types of references to .so files. However, everything about interop assemblies written above is still valid if the library you want to link to is not a stand alone library but suitable for linking.

    Also note that creating one assembly that work on both Windows and Linux is also a difficult task.


    The last option is that you can shell out to the ffmpeg command line applications. You would have to store the data you want to process as files on disk, then carefully construct all the parameters to the command line program, call it in such a way that you both capture the output from the program as well as hide it so that the user doesn't see a console window, and finally read back the processed output from the final files.

    This is a simple way if you either can't find the right nuget package and don't want to spend time investigating how to get p/invoke or interop assemblies right, but may be finicky in the sense that you're really starting a separate program and waiting for it to complete, and you may have to parse textual output to figure out what happened during execution, such as whether it succeeded or failed.

    You can read more about this line of attack here on Stack Overflow, Execute ffmpeg command with C#.