简体   繁体   中英

C# calls C++ singleton class-based dll

I am trying to call from C# to C++ dll.

The C++ dll is a singleton class like following: .h file (simplified)

#if defined(STATS_MANAGER)
#define DllExport_StatsManager __declspec(dllexport)
#else
//    definitions used when using DLL
#define DllExport_StatsManager __declspec(dllimport)
#endif    

#pragma warning( push )
#pragma warning( disable : 4251 )

class DllExport_StatsManager StatsManager
{
private:    
    StatsManager();
    static auto_ptr<StatsManager> _single;

public:
    ~StatsManager();
    static StatsManager* getInstance();
    void SetMaskPtr(unsigned short* maskPtr);

};

.cpp file (simplified)

#include "stdafx.h"
#include "StatsManager.h"
#include "ImageStats.h"

auto_ptr<LogDll> logDll(new LogDll(L".MyLoggingUnmanaged.dll"));
wchar_t message[256];

typedef void (_cdecl *statsPrototype)(long chan, long &numROI, long * min, long *max, double *mean, double *stdDev);

void (*statsFunctionPointer)(long chan, long &numROI, long * min, long *max, double *mean, double *stdDev) = NULL;

bool StatsManager::_instanceFlag = false;

bool StatsManager::_setupFlag = false;

StatsManager::StatsManager()
{
    SetThreadBusyStatus(FALSE);
    SetDataPtr(NULL);
    SetMaskPtr(NULL);
    hThread = NULL;
}

StatsManager::~StatsManager()
{
    _instanceFlag = false;
}

auto_ptr<StatsManager> StatsManager::_single(new StatsManager());

StatsManager* StatsManager::getInstance()
{
    if(! _instanceFlag)
    {
        try
        {
            _single.reset(new StatsManager());

            wsprintf(message,L"StatsManager Created");
            logDll->TLTraceEvent(VERBOSE_EVENT,1,message);
        }
        catch(...)
        {
            //critically low on resources
            //do not proceed with application
            throw;
        }
        _instanceFlag = true;
        return _single.get();
    }
    else
    {
        return _single.get();
    }
}

//model will call this function
long StatsManager::SetStatsMask(unsigned short *mask, long width, long height)
{
    long ret = TRUE;

    realloc(StatsManager::getInstance()->GetMaskPtr(),width*height*sizeof(unsigned short));
    memcpy(mask,StatsManager::getInstance()->GetMaskPtr(),width*height*sizeof(unsigned short));

    return ret;
}

In my C# code, I want to call SetStatsMask(unsigned short *mask, long width, long height) , but it throws exception " cannot find entry point 'SetStatsMask' in StatsManager.dll ". Here is my C# code:

[DllImport("StatsManager.dll", EntryPoint = "SetStatsMask")]
private static extern int SetStatsMask(IntPtr mask, int imgWidth, int imgHeight);

try
{
    ea.Result = mask;
    IntPtr maskPtr = Marshal.AllocHGlobal(2 * mask.Length);
    Marshal.Copy(mask, 0, maskPtr, mask.Length);
    SetStatsMask(maskPtr, width, height);
    SaveMask("d:\\myMask.csv", mask);
}
catch (Exception e)
{
    e.ToString();

}  

My C++ dll path I believe is right, so at this point I am not sure what causes this problem. Anyone can kindly give some pointers? Very appreciated. Thanks.

The compiler cannot find SetStatsMask() because it is looking for a function that is outside of a class. You cannot use DllImport to call the c++ class' function in this way.

I was going to recommend creating a function outside of the StatsManager class to call into it, but it looks like your SetStatsMask() member function doesn't need any non-public portions of StatsManager , and you could just turn it into a regular function instead of a member function and be good to go.

long SetStatsMask(unsigned short *mask, long width, long height)
{
    long ret = TRUE;

    realloc(StatsManager::getInstance()->GetMaskPtr(),width*height*sizeof(unsigned short));
    memcpy(mask,StatsManager::getInstance()->GetMaskPtr(),width*height*sizeof(unsigned short));

    return ret;
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM