C++/CLI Dll with C# interop issue

5

I have 3 projects in one solution.

I have :

  • a native C++ dll,
  • a C# Winform,
  • and a proxy C++/CLI without pure mode to do the link between the 2 others projects (and use the native function in the managed code in C#)

So when I launch the application all work. But when I push the button "Generer" in my winform wich execute the function NativeMethod::Test() of the C++/CLI that it crash and I have this pop-up message :

An unhandled exception of type 'System.BadImageFormatException' occurred in System.Windows.Forms.dll

Additional information: Could not load file or assembly 'EngineInterfaceWrapper.dll' or one of its dependencies. n'est pas une application Win32 valide. (Exception from HRESULT: 0x800700C1)

When I go in project proprieties in Conf. Properties -> Linker -> Advanced : Target Machine, it's set with the value "MachineX86" for my C++ native and managed DLL and my WinForm is in X86 too. I tired many configurations but it don't work.

Edit:

The problem is may be the header "TradeEngine.h"" in the C++/CLI header : EngineInterfaceWrapper.h. Because when I unlink the native C++ Dll (and deleting all code in the CLI wrapper) if I build the solution it will work but if "#include "TradeEngine.h"" is always in the CLI header, I will have the same error. Do you have an idea?

Edit: --Resolved--

I have finally found the problem. It's the boost library called in my native C++ .h. As the wrapper need to have the native header, it link also the Boost library (even with my pragma in the code, it's strange) and Boost create many problems when is invoked in a managed code so I put the headers from the native .h to the native .cpp and all works. Thank you all for your help me.

Code :

native C++

TradeEngine.h

#ifdef TRADEENGINE_EXPORTS
#define SYMBOL_DECLSPEC __declspec(dllexport)
#define SYMBOL_DEF
#else
#define SYMBOL_DECLSPEC __declspec(dllimport)
#define SYMBOL_DEF      __declspec(dllimport)
#endif

#pragma managed(push, off)
#include <curl/curl.h>
#include <boost\filesystem.hpp>

#include <boost\tokenizer.hpp>
#include <boost\lexical_cast.hpp>
#include <boost\thread.hpp>
#pragma managed(pop)

EXTERN_C SYMBOL_DECLSPEC void __stdcall Test(void);

TradeEngine.cpp

SYMBOL_DECLSPEC void __stdcall Test(void)
{
}

C++/CLI

EngineInterfaceWrapper.h

#pragma once

#include "TradeEngine.h"

using namespace System;
using namespace System::Runtime::InteropServices;

namespace EngineInterfaceWrapper {

    public ref class NativeMethod
    {
    public:
        static void AjoutColonneDifferenceCourtClotureOuvertureReelle(void);
        static void Test();
    };
}

EngineInterfaceWrapper.cpp

#pragma region Includes
#include "stdafx.h"
#include "EngineInterfaceWrapper.h"
using namespace EngineInterfaceWrapper;

#include <msclr/marshal.h>
using namespace msclr::interop;
#pragma endregion

void NativeMethod::Test()
{
    ::Test();
}

C# Winform

Program.cs

namespace TradeInterface
{
    static class Program
    {
        /// <summary>
        /// The main entry point for the application.
        /// </summary>
        [STAThread]
        static void Main()
        {
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);
            Application.Run(new Form1());
        }
    }
}

Form1.cs

generer_Click() is the event launched by the button when the user click on Generer.

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

using System.Runtime.InteropServices;
using EngineInterfaceWrapper;

namespace TradeInterface
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void generer_Click(object sender, EventArgs e)
        {
            NativeMethod.Test();
        }
    }
}
c#
visual-c++
dll
c++-cli
interop
asked on Stack Overflow Jun 27, 2011 by bdelmas • edited Mar 11, 2015 by Deduplicator

2 Answers

8

I have found the solution :

http://marc.info/?l=boost-users&m=123425857320026

In Configuration Properties -> C/C++ -> Preprocessor -> Preprocessor Definitions add BOOST_ALL_DYN_LINK in order to force the usage of the DLLs. In addition copy the necessary DLLs to the directory where the executable resides. E.g. copy boost_thread-vc90-mt-gd-1_XX.dll to MyApp/bin/Debug.

answered on Stack Overflow Mar 9, 2012 by Seçkin Durgay • edited Mar 9, 2012 by Seçkin Durgay
4

One reason can be you are trying to load a native 32-bit dll in a 64-bit process. Make sure you have platform target set to x86 in your app to force your application to run inside WoW64.

answered on Stack Overflow Jun 27, 2011 by InBetween • edited Jun 27, 2011 by ildjarn

User contributions licensed under CC BY-SA 3.0