[C++ MDL Connect] Questions regarding native MDL

Hi all,

I have been experimenting building a native solution and have a few questions, hopefully someone might be able to give some advice to save me pulling any more hair out!

  1. Is it possible to build a CLR class library and load that in Microstation, without the use of bmake? I assume if this was possible the classes would need to be decorated with attributes to inform Microstation that they are commands and define the main entry point. From what I've gathered it seems the bmake takes care of this by compiling with all the correct resources and output them along with a ma file for loading the command table into microstation, however it is quite a complicated system with limited information/documentation available, and since I do not really understand how to configure it correctly I would love to remove it from the equation if possible!
  2. If bmake is required, is it possible to create a CLR solution and reference/call my own .NET class library? I managed to build a C++ MDL with command table etc. but as soon as I make a call to any .NET methods it fails to compile with error "System::Object not found, missing /clr option or missing import of standard assemblies?". I do not get this error in a standard CLR project that does not use a make file for compiling (compiles straight to dll).
  3. Is it possilble to use XML to define the command table in C++, similar to C#? Or is this something I would need to build myself (create the defines and Command Id's etc. through a pre-build routine)

Really hoping to figure out these last few pain points, as I think that a mixed language solution would provide the best of both worlds for Microstation development provided I can sort out these last few teething issues
Thanks!


Ed

  • Hi Ed,

    I have been experimenting building a native solution

    It's a bit weird you wrote you experiment with native solution and in the first question you mention CLR class, which is "by definition" NET object. Maybe naming confusion, because you mix native code with C++/CLI, which is standard NET assembly?

    Maybe it would make more sense when you do not use "CLR class" term (because it's very general) and exactly specify what you want to achieve using what langauge (C#, able to produce pure code or C++/CLI producing mixed code).

    hopefully someone might be able to give some advice to save me pulling any more hair out!

    To keep your hairs intacted, think about your question as based on misunderstanding of core concepts, so even though they can be answered, they sounds weird.

    Is it possible to build a CLR class library and load that in Microstation, without the use of bmake?

    Let's assume you do not think CLR class library, but NET assembly created using C++/CLI. Such assembly is nothing special, and bmake does not anything magical, so yes, you can create such assembly (which contains mixed CIL code) even manually. bmake does nothing else than it calls other tools, using command line, one by one, with correct parameters.

    is it possible to create a CLR solution and reference/call my own .NET class library?

    C++/CLI PRODUCES NET assembly (and not native dll), so it can reference, and can be referenced, by any other NET project, based on any NET langauge.

    I managed to build a C++ MDL with command table etc. but as soon as I make a call to any .NET methods it fails to compile with error "System::Object not found, missing /clr option or missing import of standard assemblies?".

    Please explain exactly what you want to achieve, or better, to share your code. C++/CLI is typically used to wrap native code and publish NET API (in this way, the most of MicroStation NET API is implemented). I guess an opposite direction (wrap NET API to be called from native) would be also possible, but I do not recall any such example (probably it's rare requirement).

    Is it possilble to use XML to define the command table in C++, similar to C#?

    No. C++ has own system to define command table, based on MicroStation resources. In fact, two different mechanisms exist in native code: class command table and XCommands.

    Regards,

      Jan

  • Is it possilble to use XML to define the command table in C++, similar to C#?

    Unfortunately, Bentley Systems have evolved two different and incompatible technologies to define and implement a command table.

    However, it should be possible to write an XLS transformation that would convert the .NET XML command table into a C++ resource source table.  Then we could write an XML command table, irrespective of the technology chosen to build the application.

     
    Regards, Jon Summers
    LA Solutions

  • Thanks Jan,

    I haven't done much with C++ yet... hence my limited knowledge! To elaborate further:

    you experiment with native solution and in the first question you mention CLR class, which is "by definition" NET object

    My (probably incorrect) understanding was that CLI / CLR were essentially the same thing, for writing native C++ code that could interact with .NET classes. I guess I'm just confused though Smiley

    Please explain exactly what you want to achieve

    What I was trying to achieve was a mixed language solution, using C++ as my main "addin", and then execute either C++ or C# commands using a "command handler" method. My process was as follows:

    1. Created native commands using this guide https://communities.bentley.com/products/programming/microstation_programming/w/wiki/52106/building-a-simple-mdl-application
    2. Created a solution file and added command numbers etc.
    3. Enabled "CLR" in the C++ project
    4. Changed the output to "Make file"
    5. Under "NMake" added all the Preprocessor definitions, include paths, build commands etc.
    6. Added a .NET class library project to the solution
    7. Referenced the .NET dll in my C++ project
    8. Attempted to execute a .NET method from one of the commands, but it throws the above-listed error. The command:
      #include <Mstn\MdlApi\MdlApi.h>
      #include <Mstn\ISessionMgr.h>
      #include <Mstn\MdlApi\mselems.h>
      #using <MyCSharpLib.dll>
      
      void CmdExecute(WCharCP unparsedP)
      {
          MyCSharpNamespace::HelloWorldManaged().Execute();
          
          return;
      };

    It would seem that it is possible to build a mixed language solution, at least according to this part of the wiki: https://communities.bentley.com/products/programming/microstation_programming/w/wiki/52410/writing-add-ins-in-c-cli

    Regarding what you said earlier about CLI being a kind of .NET output, it is starting to make sense why this part of the wiki is under the header for managed code, and likely the reason I could not get this working properly within my native solution! The bit that confused me is that it still uses make files and C++ code so I assumed that it was native C++ with the added benefit of C# interoperability.

  • Hi Ed,

    My (probably incorrect) understanding was that CLI / CLR were essentially the same thing

    Well, they are, but they are something completely differnt than what you mean ;-)

    • CLI is ECMA standard for Common Langauge Infrastructure (do not confuse with "command line interface"). Technically it defines how IL (intermediate langauge) looks like and how it works.
    • CLR is Common Language Runtime, Microsoft implementation of CLI standard.

    But, I think we are discussing C++/CLI, which is (in fact proprietary) language, designed by Microsoft, adopting C++ to fit CLI specifications.

    What I was trying to achieve was a mixed language solution, using C++ as my main "addin", and then execute either C++ or C# commands using a "command handler" method

    It would be possible, because C++/CLI is just a tool,. allowing to mix native and managed code, but I never tried to use it in this way (reasons below). You can find examples on Internet how to call managed code from native, using C++/CLI wrapper, on Internet, but I guess the most of examples for MicroStation is "an opposite way": How to call (missing) native functionality from NET code.

    My question is why to do something like this? It's a plenty of work, requiring extra effort (C++/CLI is not intuitive language) for close-to-zero benefits. When you have C++ app (it's not "addin") for MicroStation, probably the only reason why to call anything from NET is GUI, that can be implemented using WPF. Plus, of course, when some 3rd party external NET library is required.

    My process was as follows

    It is extremely complicated in my opinion. It's like "There are several areas, where I can do mistakes. So, I will use all of them together."

    I would prefer to keep things as simple as possible. Use bmake and Visual Studio Code until functional result is obtained. Things like to integrate the whole system to (over)complex Visual Studio configuration can be benefit in future, but does not bring any extra value to a process of compilation (but can help with C++/CLI).

    The bit that confused me is that it still uses make files and C++ code so I assumed that it was native C++ with the added benefit of C# interoperability.

    It is a huge misunderstanding (of several topics)!

    • make files are not tight to native code in any way! You can build NET assemlby using the same way, because the process is completely the sime (code is compiled and linked). Visual Studio does it the same, the only difference is that it calls MSBuild with .csproj (which is technically make file), and not bmake and mke file.
      bmake, with macros defined in mki files, can do (and is used by Bentley) plenty of things, not compilation only, but also lazy assembly attributes settings, encoding xml command tables, applying digital signatures...
    • When any piece of the code is managed, the result must be NET assembly! There is no way how to include managed code into native dll, because mandatory condition to run managed code is to start CLR (and native dll does not contain this information).
    • C++/CLI produce mixed code, which is NET assembly, containing both managed and native code. It brings plenty of limitation, but the benefit is clear: It is possible to create efficient bridge between manged and native world (but it is always run in managed runtime).
      C++/CLI itself is "C++ with extended syntax to work with managed data types". Wery special feature is that imarshalling (complex and costly conversion between managed and native) is done mostly automatically (sometimes helper classes are necessary), at runtime or prepared during compilation.

    With regards,

      Jan

  • Thanks for a very detailed reply Jan! I will certainly heed your advice and keep things simple moving forward. I was hopeful that perhaps I could set this solution up in a simple way, keeping the .NET and C++ code separate except for when calling a C# command was required, however it seems that might be a lot more complicated than I first imagined... At least I learnt a lot in the process! Maybe I'll revisit a mixed language or C++ MDL solution in the future, but for now I think it would be best to stick with .NET API and keep things simple.

    Thanks a lot for all the help,

    Ed

  • however it seems that might be a lot more complicated than I first imagined..

    \Well, crossing borders between managed and native is alwyas complex.

    Often it requires to think a lot about memory management on both sides, because memory cannot be shared, so it's about proper allocation and freeing objects ... which leads to IDisposable interface on managed side.

    On the other hand (what is my experience when I implemented wrappers around native functionality to be available in NET), it is "templated", so when you do first several projects, the next ones like mostly copy of concepts and structure.

    Maybe I'll revisit a mixed language or C++ MDL solution in the future

    You can start with mixed code example, delivered with MicroStation SDK. It does not solves managed/native marshalling process, but shows how the project tiself looks like and how make file is done. It creates NET addin, written not in C#, but in C++/CLI.

    but for now I think it would be best to stick with .NET API and keep things simple.

    Yes, NET is the simplest way (but with some API limitations and also slower a bit). C++ is the second one, because it is more complicated langauge ;-)

    To chose one or second and to do not mix native and managed should always be preferred. But, when 95% of functionality can be done in NET, there is no reason to switch everything to C++, and C++/CLI can be used to solve these missing 5% ;-)

    With regards,

      Jan

  • Thanks Jan, appreciate the advice. Definitely keen to explore C++ more in the future, for that 5% if/when I hit that road block!