//
About

I’ve been in software development for nearly 20 years specializing in C++, COM and C#. It’s truly an exicting time we live in, with so much resources at our disposal to gain and share knowledge. I hope my blog will serve a small part in this global knowledge sharing network.

For many years now I’ve been deeply involved with C++ development work. However since circa 2010, my work has required me to use more and more C# with a particular focus on COM interop.

I’ve also written several articles for CodeProject. In recent years I’ve concentrated my time more on helping others in the MSDN forums.

Please feel free to leave a comment whenever you have any constructive criticism over any of my blog posts.

Discussion

21 thoughts on “About

  1. Hello Lim!

    I’ve recently started working with some P/Invoke implementations between C# and C++.
    I ran into some complications when trying to pass a complex struct between the two. I spent hours scouring the web for comprehensible information on the topic – then I found several of your wonderful posts on the msdn forums.

    I want to thank you for your easily comprehensible and detailed answers – they really helped me out.

    //JM

    Posted by Johan Mannerqvist | April 16, 2012, 4:34 pm
  2. I am in the same situation as you are, 20 years doing software, all the way in c++, and recently working on c#.
    With C++, you can always ask why it’s like that, but with C#, more often it’s just the way it is, not much reasoning.
    That’s why I am not very much into the high level stuff. Are you in the states?

    Posted by Rio Wing | June 9, 2012, 5:12 pm
    • Hello Rio,

      I am in Singapore. Yes, I think C++ is a better language in many ways. Things are much more controllable. I really like the way destructors are automatically called when an object goes out of scope.

      With C#, this feature is no longer predictable. We are advised to use Dispose. I think there’s a different philosophy altogether with the presence of the runtime.

      Cheers,
      – Bio.

      Posted by Lim Bio Liong | June 10, 2012, 8:38 am
  3. Hi Bio Liong,
    Hock Yan. I’m no longer programming but wanted to rebuild my skills (C++, C#, Java, Javascript, etc.). May need some help.

    Posted by chanhy | February 20, 2013, 8:33 am
  4. Some really interesting reading, but I seem to have a sitaution that no one seems to cover. Long time C/C++/assembler programming going to .net of course.

    BUT the situation I have found is a bit odd. I have a new system working, which uses MEF to load some assemblies for processing of ‘jobs’. No problems at all, the main engine even loads a few COM objects and passes references to them to the loaded assemblies, no problems.

    BUT I have a situation where I need to create a ‘logging COM interface’ in the .net main .EXE. This interface is for a defined interface ICTILog. No problems I was able to manually build the interface and a class. BUT NOW I need to pass a IDIspatch of that object I created into one of the COM objects as a properly put. Again not really a problem since I proved I could again create a true COM object of our logger and pass it in.

    BUT we want to log everything to log4net. so basically redirecting the loeaded COM objects to call back into the main EXE COM object simulation and it will call log4net. Along with capturing say console output, and the trace .net output etc. So that way everything is ine one place.

    BUT I can’t seem to figure it out at all. How to get a IDispatch I can pass into ‘abc.LoggingObject = ????’.

    I even tried using DispatchWrapper but that didn’t work either.

    Posted by Michael Shiels | August 20, 2013, 8:36 pm
  5. Hi Bio Liong, could you contact me promptly…some news for you.

    Posted by chanhy | November 16, 2013, 12:42 pm
  6. Hi Bio,
    I need your advice on passing double 2D arrays from C# to C++. Actually, I followed your blog on integer which worked perfectly. On doubles I am still struggling ..
    Many thanks.

    Posted by steve | October 20, 2015, 4:13 pm
  7. Hi! On the MSDN forum, I found a discussion where you’re implementing a MagTek Intellistripe 65 reader in C#.
    I’m trying to do the same thing, but I’m having quite some issues with my implementation and I was wondering if you’re interested in sharing your work? 🙂
    The feedback from MagTek is not optimal; they (still) don’t have any C# examples; nor a functional library that can be used along with this device.
    Looking forward to hear from you!
    Best regards,
    Steven

    Posted by Steven | June 4, 2018, 2:15 pm
    • Hello Steven,

      1. Are you referring to the following MSDN post ? :

      “Unsafe code, pointer to LPVOID, LPSTR”
      https://social.msdn.microsoft.com/Forums/en-US/907cd779-c344-4ab4-bb2b-85a60e6851e3/unsafe-code-pointer-to-lpvoid-lpstr?forum=csharplanguage

      2. If so, please note that the code examples that I used in that post were -not- implementations for the MagTek Intellistripe 65 reader.
      – For illustrative purposes, I wrote some sample McpEnum() and McpOpen() code.
      – These, however, were dummy samples and are not working MagTek Intellistripe 65 reader code.

      3. If you were referring to the C# code that calls into the MagTek reader (via MCPapi.dll), note that the code samples that I wrote in the post were limited to calling McpEnum() and McpOpen() only.
      – I personally am not familiar with the MagTek Reader nor its APIs.
      – I was showing the forum member iHijazi (the person who made the original post) how his _MCPBUS structure should be coded in C#.

      4. Sorry Steven, I don’t think I can provide any help here.

      – Bio.

      Posted by Lim Bio Liong | June 4, 2018, 6:50 pm
      • Hello Bio,

        Thanks for the quick feedback! And indeed, that was the post I was referring to!
        I’ll see if I can contact iHijazi about his implementation.
        Best regards,
        Steven

        Posted by Steven | June 5, 2018, 10:53 am
  8. Hello Bio!
    First off, I want to thank you for all the effort you put into the articles (both on CodeProject and here).
    I have learned so much from you, and again, I can not thank you enough.
    I am embarrassed for asking for help here, but I have no choice, so please forgive me if I am bothering you.
    I will try to be as brief as possible, but please feel free to ask follow up questions if you need clarification.
    Here it goes:
    I want to fire events from worker thread (you wrote an article about this on CodeProject -> Understanding The COM Single-Threaded Apartment Part 2, section Demonstrating Advanced STA) using Free Threaded Marshaler ( I have added ATL Simple Object with threading model Both and aggregated Free Threaded Marshaler).
    This topic was not covered in the article but I wanted to learn to fire events this way to.
    My question is this:
    Do I still need to use Global Interface Table or CoMarshalInterThreadInterfaceInStream or can I just directly call Fire_SomeEvent?
    I am adding below short code snippet to explain better what I mean:
    STDMETHOD CSimpleObject::StartThread(void)
    {
    threadHandle = CreateThread(NULL, 0, ThreadFunction, this, 0, NULL);
    if(NULL == threadHandle) return HRESULT_FROM_WIN32( GetLastError() );
    return S_OK; // I will wait for thread exit elsewhere
    }
    DWORD WINAPI CSimpleObject::ThreadFunction(LPVOID arg)
    {
    CSimpleObject *c = (CSimpleObject *)arg;
    c->Lock();
    // is this OK or should I marshal interface like you did in the article (Demonstrating Advanced STA) ?
    c->Fire_SomeEvent();
    c->Unlock();
    return 0;
    }
    Thank you for sparing some time to read this comment.
    Even if you do not answer, I will understand.
    Again, BIG thank you for the articles, they helped a lot! Keep up the good work!
    Regards,
    Nenad

    Posted by Nenad | July 18, 2018, 8:52 am
    • Hello Nenad,

      1. You -do- need to use either the Global Interface Table or the CoMarshalInterThreadInterfaceInStream() API to Marshal the Event Sinks from the CSimpleObject object to the ThreadFunction() thread.

      2. Also, ThreadFunction() will need to be a COM thread, i.e. it must call ::CoInitialize() (or ::CoInitializeEx()) and ::CoUninitialize().

      3. The fact that CSimpleObject uses a Free Threaded Marshaler is not relevant in the context of what you are doing here, which is to make CSimpleObject fire events to its event sinks.

      4. If ThreadFunction() is not initialized as a COM thread, Fire_SomeEvent() will be called on that thread and this can foul up all the COM rules, e.g. the event sink will be invoked on this thread instead of on the appropriate thread of the sink.

      5. The only situation in which Free Threaded Marshaling becomes relevant is if the sink objects aggregate it.
      – But even then, in order that the sinks’ FTMs become effective, ThreadFunction() must be initialized as a COM thread and the event sinks must be marshaled to ThreadFunction().

      Posted by Lim Bio Liong | July 23, 2018, 11:17 am
      • Hello again!

        Thank you so much for the advice!

        The documentation confused me, that is why I had to ask, in order to be 100% sure if I needed to marshal or not.

        I agree with everything else you have said, it is in congruence with the content of your various articles.

        Regards,
        Nenad

        Posted by Nenad | July 26, 2018, 7:54 am
  9. Hi Bio!

    I tried to delete my reply and replace it with this content but failed to do so.

    I have decided to ask you in a new comment for an opinion about following idea :

    I could create a hidden window in my COM object, and use PostMessage (with custom defined message) from worker thread to communicate with the COM object.

    I could fire event in a handler for custom message.

    I have already coded a small demo and it works.

    Since this is my first time with this approach, I was wondering if you could answer these short questions:

    1. Is this approach better/worse in any case than interface marshaling?

    2. Must worker thread be a COM thread as well (I believe it must be, but want to be sure) ?

    3. Have I missed any pitfall ?

    Again, I apologize for disturbing, but this idea is really interesting to me, so I had to ask.

    Thanks again for the previous answer, it was highly instructive.

    Regards,
    Nenad

    Posted by Nenad | July 26, 2018, 8:37 am
    • Hello Nenad,

      1. >> Is this approach better/worse in any case than interface marshaling?
      1.1 Answer : it is not a valid approach at all even though it appeared to have worked for your specific case.

      1.2 The reason : your CSimpleObject uses the “Both” threading model. Hence it could be created in an MTA thread.

      1.3 If it was created in an STA thread (most likely the situation in your case), it will work. This is because an STA thread must provide a message loop.

      1.4 If it was created in an MTA thread, that thread must contain a message loop in order for the hidden window to receive messages. The problem is that it is the client which creates CSimpleObject and you are not able to control whether any message loop is created in the client’s thread.

      2. >> Must worker thread be a COM thread as well (I believe it must be, but want to be sure) ?
      2.1 If the thread makes no interface method calls, and merely sends a message to the hidden window, it does not have to be a COM thread.

      3. >> Have I missed any pitfall ?
      3.1 Yes : the fact that a “Both” threading model object can live in an MTA.

      Posted by Lim Bio Liong | July 26, 2018, 11:26 am
      • Thanks again for helping out!

        I apologize for the scarce information, new demo app is STA.

        I was just wondering if PostMessage + hidden window was viable option to marshaling, and if it is a better choice than marshaling.

        Regards,
        Nenad

        Posted by Nenad | July 27, 2018, 11:26 am
      • Hello Nenad,

        1. >> new demo app is STA.
        If your client thread is STA, then your hidden window and message approach will work in that the CSimpleObject’s methods (whatever they be, including Fire_SomeEvent()) will be executed in the thread in which CSimpleObject was created (i.e. an STA thread).

        2. >> I was just wondering if PostMessage + hidden window was viable option to marshaling, and if it is a better choice than marshaling.
        2.1 It is not a viable option and it is not a better choice over marshaling even though it works in your specific case.

        2.2 It is better to use standard marshaling code and not to tinker with one’s own custom method.

        Posted by Lim Bio Liong | July 27, 2018, 12:43 pm
  10. Dear Bio,
    Thanks a lot for this blog. This is one of the few places I have found where one can found clear answers to complex questions!
    Here is a puzzle for you, I would be super grateful if you had some suggestions.

    I want to call .NET methods from C++ through .Invoke with a char[] parameter:
    for instance: StringBuilder.Insert(int index, char[] value)
    I reasoned that from C++, I should pass a safearray of VT_UI2, with variant type VT_ARRAY+VT_UI2, and that would be marshaled to a char[]. But I get an “incorrect parameter” error.
    When I look at the managed side in a test object, I can see that the parameter is marshaled as an UInt16[] array rather than char[].

    Any recommendations? Thanks!

    Posted by haton | December 29, 2020, 1:48 am

Leave a reply to Johan Mannerqvist Cancel reply