Active1 year, 5 months ago
We're trying to develop a cross-platform app for desktops (Windows and Mac) using C#. The app contains a massive amount of platform dependent stuff and our team lead wants us to write all of that code in C#. The easy way to do this would be to write wrappers in C++ and just reference the libraries in the C# code and let the C++ libraries deal with the platform stuff.. alas, that is not to be.
I'm trying to set up a library using Visual Studio for Mac. I'm hoping to be able to provide a single interface in a single library to grant access to the native text to speech library on the current platform -- preferably without making two assemblies. The text-to-speech library in C# for Windows isn't available on Mac, so we don't really have an alternative option than to provide some bridge ourselves.
I'm happy with having the library do operating system lookup to determine which operating system it's running on and/or attempting to load a bunch of native libraries and just using which ever library will load.
If I must, having a single project that will allow me to write two implementations will have to do. I haven't found a way to create a library project in Visual Studio for Mac, that will allow me do so however. The only type of project that will allow multiple implementations seem to require that the implementations are either for iOS or for Android.
![Is There Visual Studio For Mac Is There Visual Studio For Mac](https://visualstudio.microsoft.com/wp-content/uploads/2016/11/3_VSMac_DesignerIntellisenseglobal-search-516@x2.png)
Best Answer: Visual Studio is an IDE for a suite of Microsoft Windows programming languages. If you are simply looking for an IDE, take a look at Eclipse. If you are looking for programming languages, take a look at C/C++ from GNU or Java from Sun. Currently you would need to create an extension for Visual Studio for Mac to add a new project template. Then there are two options for how to create the project template. You can use the old templating engine which is documented on the MonoDevelop website. Or you can use the new.NET Core templating engine to create a NuGet package.
8,37122 gold badges1616 silver badges4848 bronze badges
ClearerClearer
Because Microsoft's Visual Studio only runs in the Windows environment, however, it is impossible to use Visual C++ directly on a Macintosh. We should point out that by installing VirtualPC, a Macintosh user may create a Windows simulator on their machine and thereby run Microsoft Visual C++. Developer Community for Visual Studio Product family. Get help from our community supported forum.
1 Answer
You have a good question. There's probably some trade-offs with your solution. The ultimate answer really depends on what you mean by platform dependent. For example, if you are starting up a process to start external applications and you are simply switching between one application and another, you can probably handle that without too much complication. If you are talking P/Invoke with native libraries, then there's a little more that has to be done. However if you are linking with libraries that only exist on one platform, you probably will need to use multiple assemblies.
External apps
You probably won't need to use
#if
statements in this situation. Just set up some interfaces, and have one implementation per platform. Use a factory to detect the platform and provide the right instance.In some cases it's just a binary compiled for a specific platform but the name of the executable and all the parameters are defined the same. In that case it's a matter of resolving the right executable. https://zoever972.weebly.com/visual-studio-for-mac-os-free-download.html. For a bulk audio converter app that could run across Windows and Linux, I had a static initializer resolve the binary name.
Nothing fancy here. Just good ol' fashioned classes.
P/Invoke
P/Invoke is a bit trickier. Andriod studio for mac. The bottom line is that you need to ensure the right version of the native library is loaded. On windows you would P/Invoke
SetDllDirectory()
. Different platforms may not need that step. So this is where things can get messy. You may need to use #if
statements to control which call is used to control resolving your library path--particularly if you are including it in your distribution package.![Studio Studio](https://mspoweruser.com/wp-content/uploads/2017/05/Visual-Studio-for-Mac.png)
Linking to completely different platform dependent libraries
The old school multi-targeting approach may be useful here. However it does come with a lot of ugliness. In the days where some projects attempted to have the same DLL target Silverlight, WPF, and potentially UAP, you would have to compile the application multiple times with different compilation tags. The challenge with each of the platforms above is that while they share the same concepts, the platforms are sufficiently different that you have to work around those differences. This is where we get into the hell of
#if
.This approach also requires hand editing the
.csproj
file to handle platform dependent references. Since your .csproj
file is an MSBuild file, it's entirely possible to do in a known and predictable manner.#if hell
You can turn on and off sections of code using
#if
statements so it is effective at handling the minor differences between the applications. On the surface it sounds like a good idea. I even used it as a means to turn on and off bounding box visualization to debug drawing code.The number 1 problem with
#if
is that none of the code that is turned off is evaluated by the parser. You may have latent syntax errors, or worse, logic errors waiting for you to recompile the library. This becomes even more problematic with refactoring code. Something as simple as renaming a method or changing the order of parameters would normally be handled OK, but because the parser never evaluates anything turned off by the #if
statement you suddenly have broken code that you won't see until you recompile.All of my debug code that was written in that manner had to be rewritten after a series of refactorings broke it. During the rewrite, I used a global config class to turn on and off those features. That made it refactor tool proof, but such a solution doesn't help when the API is completely different.
My preferred method
My preferred method, based on many painful lessons learned, and even based on Microsoft's own example, is to use multiple assemblies.
Is There Visual Studio For Mac
One core NetStandard assembly would define all the interfaces and contain all the common code. The platform dependent implementations would be in a separate assembly that would add features when included.
This approach is exemplified by the new Configuration API and the current Identity architecture. As you need more specific integrations, you simply add those new assemblies. Those assemblies also provide extension functions to incorporate itself into your set up. If you are using a dependency injection approach, those extension methods allow the library to register it's services.
This is about the only way I know of to avoid
Berin LoritschBerin Loritsch#if
hell, and satisfy a substantially different environment.35.9k55 gold badges6666 silver badges141141 bronze badges