none
Problem calling a C# dll from a mixed C++ CLI dll RRS feed

  • Question

  • Hello,

     

    I have a mixed C++/CLI dll and a managed C# class library dll. I need to call the C# managed dll from the C++ mixed dll.

    The mixed dll is actually a Firefox plugin, this construct was made to be able to call the C# dll from javascript on a Firefox extension. I know I could do this using COM interop but that's something I want to avoid, for starters, you have to register the C# dll and this is a deployment problem I don't want to have later.

    Ok. I have a something that compiles and works, until the C++ code tries to call a method from the wrapper class that encapsulates calls to C# code, on that very moment I get a FileNotFoundException telling me that it can't find the C# dll (called Common.dll). That dll is copied in the same folder than the C++ dll, a Firefox folder for plugins.

    I get this error both executing normally and debugging.

    For now, I'm trying to call a static method of a static class. The C# code looks like this:

     

     

    public static class Data<br/>
    {<br/>
      private const string CURRENT_VERSION = "0.1";<br/>
    <br/>
      public static string GetEmptyData()<br/>
      {<br/>
        return "<?xml version=\"1.0\" encoding=\"utf-8\" ?>\n<DataRoot xmlns=\"http://tempuri.org/DataDef.xsd\" DataVersion=\"0.1\" RelatedText=\"\"></DataRoot>";<br/>
      }<br/>
    }
    

    As you can see, it's just a method that returns a string.

    The C++ wrapper code is this (header file):

    class __declspec(dllexport) DataWrapper
    {
    public:
      DataWrapper(void);
      ~DataWrapper(void);
    
      static void GetEmptyData(LPSTR sData);
    };
    

    And the cpp file:

    #include "StdAfx.h"
    #include "DataWrapper.h"
    
    #include <msclr/marshal.h>
    using namespace msclr::interop;
    
    #include <strsafe.h>
    
    using namespace System;
    using namespace System::Runtime::InteropServices;
    using namespace Common;
    
    DataWrapper::DataWrapper(void)
    {
    
    }
    
    DataWrapper::~DataWrapper(void)
    {
    }
    
    
    void DataWrapper::GetEmptyData(LPSTR sData)
    {
      String ^ str;
      str = Common::Data::GetEmptyData();
    
      // Convert System::String to PCWSTR.
      marshal_context ^ context = gcnew marshal_context();
      PCSTR pszStr = context->marshal_as<const char*>(str);
      DWORD dwSize = lstrlenA(pszStr) + 1;
      HRESULT hr = StringCchCopyA(sData, dwSize, pszStr == NULL ? "" : pszStr);
      delete context; // This will also free the memory pointed by pszStr
    }
    

    On another cpp file, there's a method Firefox calls when the javascript tries to call a function from your plugin. I have a test.html file with a button that does just that. This function starts like this:

    bool ScriptablePluginObject::Invoke(NPIdentifier name, const NPVariant *args, uint32_t argCount, NPVariant *result)<br/>
    {<br/>
     if (name == sFoo_id)<br/>
     {<br/>
      //Creates and shows a MessageBox<br/>
      MessageBoxA(NULL, "Hello! I'm the C++ program", "MyPlugin", MB_OK);<br/>
    <br/>
      //Calls a Javascript alert (in browser)<br/>
      NPObject* window;<br/>
      if (NPN_GetValue(m_pNpp, NPNVWindowNPObject, &window) != NPERR_NO_ERROR)<br/>
      {<br/>
        MessageBoxA(NULL, "Error getting window object", "MyPlugin", MB_OK);<br/>
        return false;<br/>
      }<br/>
      <br/>
      NPVariant message;<br/>
      char sMsg[65536];<br/>
      DataWrapper::GetEmptyData(sMsg);<br/>
    <br/>
    ...
    

    This method is getting called because I put a breakpoint on "XtyleDataWrapper::GetEmptyData(sMsg);" and the execution stops there when I'm debugging. I get the FileNotFoundException just afterwards, when the C++ dll tries to call the method.

    As I've said, the C# dll is copied in the same folder than the C++ dll.

    I can see the first MessageBox too.

    What am I missing here?

     

    Thanks!

    -Sergi Díaz

    Tuesday, July 27, 2010 10:03 AM

Answers

  • You have to help the domain to resolve your assemblies

    See following for an example:

    http://blog.codinglight.com/2009/07/assembly-resolution-with.html

    • Marked as answer by Sergi Diaz Tuesday, July 27, 2010 2:01 PM
    Tuesday, July 27, 2010 11:33 AM

All replies

  • I've found something. If, instead of copying the C# dll in the same folder than the C++ plugin dll, I copy it besides the Firefox.exe executable, it's able to find it! So it seems that the system searches for the dll on the same folder than the executable file, not the dll that it's loading it. Or maybe it's just the working directory.

     

    Is there a way I can work around this? I suppose I could try changing the working directory, but I don't know what effect that could have on the browser's functionality.

    Tuesday, July 27, 2010 10:28 AM
  • Changing the current directory doesn't solve anything. It seems it just searches on the exe directory :(.
    Tuesday, July 27, 2010 11:12 AM
  • You have to help the domain to resolve your assemblies

    See following for an example:

    http://blog.codinglight.com/2009/07/assembly-resolution-with.html

    • Marked as answer by Sergi Diaz Tuesday, July 27, 2010 2:01 PM
    Tuesday, July 27, 2010 11:33 AM
  • Thanks! Works like a charm :).
    Tuesday, July 27, 2010 2:01 PM
  • I'm currently facing a similar task: Implementing a Firefox plugin with a combination of C++/CLI and C# code, and I like your approach avoiding the COM interop. While I'm fit with C# and JavaScript, C++ is new for me, so I try to keep that part as small as possible.

    With the help of your code I managed to setup and compile two projects that can communicate with each other using wrapper functions. But now I'm stuck with the Firefox integration and basically setting this whole project up so that everything fits together and I can start implementing the actual functionality (retrieve data from a bluetooth scanner via an external library and put it into a html form element). Could you please help me out by providing me your project source or a stripped down version of it as reference?

    Thank you,
    -- Bob
    -- djkrose@lavabit.com

     

    Thursday, March 10, 2011 11:46 PM