3
votes

So as the title states, I am looking to pass an object that is defined in an unmanaged C++ project into a managed C++/CLI project (both projects are in the same solution) while still being able to access the same methods as in the unmanaged C++ project.

This object is a class which imports functions from a separate unmanaged C++ dll (not in the same project or solution) through the means of using typedef's as shown below (excerpt of header):

#pragma unmanaged    

typedef BOOL (WINAPI *someBoolFunc) (DWORD Name, DWORD Flags, TCHAR* Text);

class INeedThisClass
{
public:
    INeedThisClass();
    ~INeedThisClass();

    someBoolFunc BoolFunc;
}; 

extern INeedThisClass ReallyNeedThisClass;

I would really like to be able to access the externed object ReallyNeedThisClass from within my managed code by just only passing the object. By having this object I wish to access it's methods through ReallyNeedThisClass->BoolFunc. What is the best way of accessing this object from my managed code?

EDIT: I've been thinking maybe there is a way of using a property to "Get" the object from the unmanaged code and then "Set" the same object in the managed code. Could this be a proper angle to approach this issue from? I've cleaned up the question a bit to get rid of useless details.

UPDATE: I've made progress on this using a wrapper for the unmanaged C++ code, but of course there are still problems. Using the above class as an example here, I will show you what I have managed to do up until now.

Project 1: Unmanaged C++ class (example above)

Project 2: Managed C++/CLR wrapper class (example below)

Wrapper.h:

#pragma once

#include "INeedThisClass.h" //Unmanaged class INeedThisClass

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

namespace INeedThisClassWrapper
{
    public ref class INTC
    {
    public:
        INTC(void);
        virtual ~INTC(void);

        delegate bool BoolFunc(UInt32 Name, UInt32 Flags, String^ Text);

    private:
        INeedThisClass *ReallyNeedThisClass;
    };
}

Wrapper.cpp:

#include "Stdafx.h"
#include "Wrapper.h"
using namespace INeedThisClassWrapper

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

INTC::INTC(void)
{
    ReallyNeedThisClass = new INeedThisClass();
}

INTC::~INTC(void)
{
    if (ReallyNeedThisClass)
    {
        delete ReallyNeedThisClass;
        ReallyNeedThisClass = NULL;
    }
}

bool INTC::BoolFunc(UInt32 Name, UInt32 Flags, String^ Text)
{
    return ReallyNeedThisClass->BoolFunc;
}

Now I am receiving errors from the compiler stating:

error C2065: 'WINAPI': undeclared identifier
error C2065: 'someBoolFunc': undeclared identifier
error C4430: missing type specifier - int assumed. Note C++ does not support default-int

Any ideas?

1
Before people start claiming this may be a duplicate question... I looked at other questions posted before this one and none had answers of real use for this situation (if they had answers at all).Brutick
You might add the links to these question the next time, helping answerers to check their inspirations.thiton
The answer depends on the type of library you want to use. Did you look at codeproject.com/KB/mcpp/usingcppdll.aspx (which you find by googling "using code from unmanaged dll in managed c++")Thomas
I did look at this prior to posting my question. This article confused me a bit because of the way they export the classes. I'm not really supposed to be playing around with the code of the class I want to access. I would rather not have to change the way the functions are imported to the unamanged class as there are other classes which depend on the way the class is written now. Do you know if this approach (with the typedef BOOL WINAPI) will still work if the class is implemented using the way I used in the question?Brutick

1 Answers

3
votes

First, you have to export INeedThisClass from unmanaged dll and import from managed one.

//unmanaged header

#if UNMANAGED_COMPILE_DEFINITION
#define EXPORT_OR_IMPORT __declspec(dllexport)
#else
#define EXPORT_OR_IMPORT __declspec(dllimport)
#endif

class EXPORT_OR_IMPORT INeedThisClass
{
public:
    INeedThisClass();
    ~INeedThisClass();

    someBoolFunc BoolFunc;
};

Also unmanaged dll must be compiled with UNMANAGED_COMPILE_DEFINITION preprocessor definiton.

Second, remove extern INeedThisClass ReallyNeedThisClass; you don't need it. Because ReallyNeedThisClass is a member of wrapper class already.

Third, you need to marshal System::String^ to TCHAR* in order to call BoolFunc

Forth, I do not remember but if you include "Windows.h" or "Winnt.h", the error about WINAPI will be gone.