AaronRobinsonMSFT / DNNE

Prototype native exports for a .NET Assembly.
MIT License
394 stars 41 forks source link

Tutorial for dummies #161

Closed DennisGundersen closed 1 year ago

DennisGundersen commented 1 year ago

Could someone please write a tutorial for dummies who can hopefully use DNNE, but don't know enough to configure and compile it?

I'm an amateur programmer, but I'd like to use DNNE in a x32 project (exporting C# functions to MetaTrader 4). I understand that I need to recompile the GitHub project code rather than using the NuGet package as it's x64, but I can't figure out how compilation is done, and I'm pretty sure this stuff is beyond many other potential users of DNNE as well.

I had great hope when I saw a Visual Studio template was posted, but to me it looks like it just creates an empty class library and sets the target to x86. There is no trace of DNNE that I can find. In any case, a tutorial would be nice for future versions and other changes. I tried starting one, but only got this far (even with guesstimations)...

  1. Download DNNE Master project from https://github.com/AaronRobinsonMSFT/DNNE.
  2. Download and install the x86 version of the wanted .NET platform (here 7.0) from https://dotnet.microsoft.com/en-us/download.
  3. Create an empty C# class library and change project properties; Target framework: 7.0, Target OS: Windows, Platform target: X86
  4. Copy DNNE Master source code in d: (as an example)
  5. Go to "D:\DNNE-master\src\msbuild" and open file "DNNE.props"
  6. Set "DnneRuntimeIdentifier" to "win-x86"
  7. Open a Terminal prompt and go to "D:\DNNE-master\src"
  8. Run "dotnet build create_package.proj"
  9. Open "D:\DNNE-master\src\dnne-pkg\bin\Release" and copy "DNNE.2.0.1.nupkg"
  10. (Only need to do this once:) In Visual Studio: Tools, Options, NuGet Package Manager, Package Sources, Add (+), Name: Local packages, Source: "D:/Downloads"
  11. Paste the file "DNNE.2.0.1.nupkg" into "D:/Downloads"
  12. Go to your Project in Solution Explorer, right click and select "Manage NuGet Packages". Select package source "Local packages".
  13. Install DNNE.
  14. Add new class with code from "D:\DNNE-master\sample"
  15. Collect underpants
  16. Yeah, I've got nothing (as this still won't work due to missing "hostfxr" and more x86 vs x64 stuff).
  17. Get rich and famous.

Re Dennis

PS! Of course I've read the Readme file, but that stuff is not really written for amateurs...

ThaDaVos commented 1 year ago

Please see my comment on another issue - I created a template for x86 based projects - like mentioned there, you can just use the latest DNNE nuget package: https://github.com/AaronRobinsonMSFT/DNNE/issues/157#issuecomment-1473884062

EDIT: I am using this for Clarion based projects, which are currently only x86

DennisGundersen commented 1 year ago

Okay... I thought the template used a local compiled DNNE version on your machine as I couldn't see anything about it, but yes, adding the normal NuGet package to my library created by this template it does indeed compile. I'm happy, but at the same time feel like I understand even less now... Is <PropertyGroup Label="DNNE"...> in .csproj the only thing it took? How can that be if the NuGet is x64?

Re Dennis

ThaDaVos commented 1 year ago

Just take it from me - NuGet does have some magic regarding that subject - it knows what to get for your specific runtime.

To answer your questions:

Is <PropertyGroup Label="DNNE"...> in .csproj the only thing it took?

Yes it was, as it's the way to reference NuGet packages

How can that be if the NuGet is x64?

You're talking about the NuGet binary? If so, does it really matter that it's a x64 binary? Bet you're using a 64x Visual Studio too, and a 64x Windows and probably a 64x browser - there are ways to go from x86 to x64 and back - the only thing NuGet is responsible for is getting the right assembly for you during/before compilation - as your project is targeting x86 - it will get the x86 assemblies and vice-versa

Just FYI - NuGet isn't part of your project, it's a development tool you use

DennisGundersen commented 1 year ago

I'm planning on connecting MetaTrader 4 to my C# library, and I know from my old solution (.NET Framework 4.x using Robert Giesecke's DLLExport) that is has to be x86, not Any CPU, and Aaron mentioned in that other post that the official NuGet was x64. Guess I underestimated NuGet. MT4 is finicky as all heck and seem to have only one error code (basically "FU"). Not very helpful. I'd still love to know how to actually compile DNNE and how this template works as I've spent a couple of weeks on it already, but I guess I'm not in a hurry since I still have to find out how to connect the rest.

So, thank you very much!

Re Dennis

ThaDaVos commented 1 year ago

You're welcome - like I said, I am doing the same but with Clarion and it also has a single error code mostly (Access Violation) or just closing itself... - if your question has be answered, please close this issue

DennisGundersen commented 1 year ago

One more question (sorry). The template seems to dump out a whole lot of files, maybe the whole .NET framework. Is that really necessary if the correct .NET framework is already installed on the machine?

ThaDaVos commented 1 year ago

You mean my template? Yeah it does - make sure during publish it's set to "Framework Dependent" - then it will only dump out a few files - don't take the files from just builds - actually publish it - also make sure in your .csproj that the following are set to false:

    <SelfContained>false</SelfContained>
    <PublishTrimmed>false</PublishTrimmed>
DennisGundersen commented 1 year ago

Oh, yeah. Don't know how to use the resulting files yet, but that looks much better. I'll try to update the template for this version. By the way, if I can make this work with Metatrader I really should share the solution with that crowd. Would that be a problem for you?

AaronRobinsonMSFT commented 1 year ago

@DennisGundersen Were the notes in the readme not helpful? You likely are missing the Runtime Identifier (RID) for x86.

AaronRobinsonMSFT commented 1 year ago

Also, the sample\ should be loadable in Visual Studio if desired. It doesn't include a native project for consuming it in the solution. However, in the sample/native directory there is a main.c that shows an example of consuming from native code.

ThaDaVos commented 1 year ago

Oh, yeah. Don't know how to use the resulting files yet, but that looks much better. I'll try to update the template for this version. By the way, if I can make this work with Metatrader I really should share the solution with that crowd. Would that be a problem for you?

You mean my template? Of course not - share it if you want - i created it to be shared and cause I have multiple projects to create the same way

DennisGundersen commented 1 year ago

@DennisGundersen Were the notes in the readme not helpful? You likely are missing the Runtime Identifier (RID) for x86.

With all due respect, I believe you are assuming way to much knowledge on the part of the readers and thereby excluding the majority of your potential users. I'm a forms-over-data dabbler (that gets nightmares remembering the c++ classes in uni even after 35+ years), but who can certainly massage lists of data in C# well enough to do auto trading in Forex as long as the InterOp bridge is set up by someone else. My guess is that there are massive amounts of hobbyists on my level that would love DNNE if they knew of it, and had a simple enough tutorial to get the plumbing done automagically without ending up like Underpants Gnomes (Southpark joke).

Something like this (not done yet):

01 Download and place the VS template package ClassLibraryforMT4WithDNNE.zip in \Visual Studio 2022\Templates\ProjectTemplates 02 Open VS, Create new project using the template (search for DNNE and look at the bottom) 03 Install DNNE from NuGet 04 Write your code 05 Publish project to folder, and make sure Deployment mode = Framework-dependent (More actions, Edit) 06 There should be two dll's (plus your extra libraries), two header, and two json files in the publish folder. 07 As I understand it the ProjectNameNE.dll is the one with DNNE included. 08 sample/native/main.c shows how to call the file from c++ 09 sample/mt4/sampleEA.mql coming soon ClassLibraryforMT4WithDNNE.zip

Re Dennis

DennisGundersen commented 1 year ago

Oh, yeah. Don't know how to use the resulting files yet, but that looks much better. I'll try to update the template for this version. By the way, if I can make this work with Metatrader I really should share the solution with that crowd. Would that be a problem for you?

You mean my template? Of course not - share it if you want - i created it to be shared and cause I have multiple projects to create the same way

Excellent. I've got a friend of mine who actually likes c++ looking at what I've got so far, and assuming we can make an automagic solution for dummies useable in MT4 I will post it on mql5.com (the forums for MetaTrader). I'll keep eveyone's names in for credit, but try to keep the setup so simple that this place won't get flooded (there are looooots of Forex traders hoping to live a work free life of leisure and riches).

AaronRobinsonMSFT commented 1 year ago

I believe you are assuming way to much knowledge on the part of the readers and thereby excluding the majority of your potential users.

I don't understand this statement. The example under sample/ does just that. Load it in VS and it produces a .NET assembly and native export without issue. The issue it seems has nothing to do with DNNE on x64 but rather DNNE when targeting x86 as x64, the default arch for .NET, works precisely as described.

I genuinely want to help here but I'm confused as to the underlying issue. Using NuGet package manager in Visual Studio to add DNNE to an existing .NET project and then marking a function with UnmanagedCallersOnly is about as easy as it gets. The tricky part is when targeting x86 as opposed to x64, which I agree can be annoyingly difficult.

07 As I understand it the ProjectNameNE.dll is the one with DNNE included.

Yes, but can be overridden using MSBuild properties - see all available options in DNNE.props.

DennisGundersen commented 1 year ago

I believe you are assuming way to much knowledge on the part of the readers and thereby excluding the majority of your potential users.

I don't understand this statement. The example under sample/ does just that. Load it in VS and it produces a .NET assembly and native export without issue. The issue it seems has nothing to do with DNNE on x64 but rather DNNE when targeting x86 as x64, the default arch for .NET, works precisely as described.

Yes, it is definitely only "missing info on using DNNE on x86" that is the problem, which is why I suggested a tutorial about that even for us dummies informing about such x86 usage, so others don't have to go through this:

I first tried to add the NuGet to my library (which was x86), and it failed. I read your reply in issue 157 to NrSlionHeart: "You should have the x86 version of the runtime installed and specify the RID. See step (3) in readme.md". Okay, I know I have the SDK from installing VS 2022, but I manually add the runtime, next what is a RID. Reading the file..... Reading again... Reading next day.... Okay, so that's RID, but I still don't see where it goes? Well, Aaron referred to the part "Generating a native binary using the DNNE NuPkg", so I guess to get a hold of an x86 version of DNNE that I can use, I have to set all those variables and recompile making a new NuGet package. Re-reading several days later. Still not sure where to put variables, but try a bunch of stuff and get so into it that I don't even pick up that the posted template solves my problem. When ThaDaVos told me all the "DNNE.props" just go in the .csproj file and then you can use the regular NuGet package, you could have floored me with a feather.

Looking at the amount of questions and reported issues historically that has been about x86, I'm a little surprised there are no notes on this available. All old posts just end with a version of "oh, I got it to work now, thanks", never a "how I made it work".

Since I'm normally not as clueless as I must seem here and now, I realize that InterOp is not a starter-level programming area, so I figured all the people here were just experienced enough with the subject that your readme made perfect sense to them, hence no one noticed that the "I watched Tim Corey's C# Mastercourse so now I'm ready for my first project" crowd would need an extra pointer for x86 projects. As I have no shame as a programmer (being an accountant), I just posted what I thought I had found out so far, and hoped someone would come along with a the right solution to make the newbie go away, if there wasn't too much work left.

I doubt I'll be the last newbie to swing by, so a quick "To use DNNE as x86, slap this XML code into your project file" post, should help.

Re Dennis

AaronRobinsonMSFT commented 1 year ago

Still not sure where to put variables, but try a bunch of stuff and get so into it that I don't even pick up that the posted template solves my problem. When ThaDaVos told me all the "DNNE.props" just go in the .csproj file and then you can use the regular NuGet package, you could have floored me with a feather.

Ah. I can absolutely fix that.

so a quick "To use DNNE as x86, slap this XML code into your project file" post, should help.

Excellent suggestion. I can make a clearer example for that.

Thank you for pointing out this confusion.

AaronRobinsonMSFT commented 1 year ago

@DennisGundersen I've updated the readme to clarify some of the confusion that people have faced. I've added more comments and examples of properties to the Sample project and hopefully reworked the readme to be more intuitive to follow. Please let me know if you think there are more things that can be done.

DennisGundersen commented 1 year ago

@DennisGundersen I've updated the readme to clarify some of the confusion that people have faced. I've added more comments and examples of properties to the Sample project and hopefully reworked the readme to be more intuitive to follow. Please let me know if you think there are more things that can be done.

Looks good to me, (now that I realize the connection between DNNE.props and .csproj, but that was probably just a blind spot on my side, not a regular thing).

Thank you very much for the help.

Re Dennis