MFC Problem with method that returns a pointer to other DLL module’s class

I have an MFC app which is a semestral final project at the university. The project’s solution includes two DLL modules: Except1 (handling errors and displaying messages), MyData (managing application data) and ProjectMFC that compiles to .exe file (the proper application project).
The project’s dependencies look like below:

Except1
|
|-->MyData
|     |
|     v
|-->ProjectMFC

According to the project guidelines in MyData and ProjectMFC files I have to create a declaration of pointer to Except1 module’s class in order to use methods from this module.

CExcept1App* pExcept;

In ProjectMFC it works.
But in MyData I get a linker error

Error LNK2019 unresolved external symbol GetExceptPtr referenced in function "public: __cdecl MY_DATA::MY_DATA(int)" (??0MY_DATA@@QEAA@H@Z)
although I’ve added additional dependencies in MyData project’s properties.

MyData.h:

// MyData.h : main header file for the MyData DLL
//

#pragma once

#ifndef __AFXWIN_H__
    #error "include 'pch.h' before including this file for PCH"
#endif

#include "resource.h"       // main symbols
#include "Except1.h"

#ifdef MY_DATA_EXPORTS
#define MYDATA_API __declspec(dllexport)
#else
#define MYDATA_API __declspec(dllimport)
#endif // MY_DATA_EXPORTS

// CMyDataApp
// See MyData.cpp for the implementation of this class
//

//template <class T, class Key>
//T* find(const T* p_begin, const T* p_end, const Key& k)
//{
//  if (p_begin >= p_end)
//      return NULL;
//
//  T* p_tmp = const_cast<T*>(p_begin);
//  for (; p_tmp != p_end; p_tmp++)
//  {
//      if (*p_tmp == key)
//          return p_tmp;
//  }
//  return NULL;
//}

class CMyDataApp : public CWinApp
{
public:
    CMyDataApp();

// Overrides
public:
    virtual BOOL InitInstance();

    DECLARE_MESSAGE_MAP()
};

class CExcept1App;

class MYDATA_API MY_POINT
{
public:
    double x;
    double y;
    char* name = NULL;
    COLORREF color;

    MY_POINT() : x(0), y(0), name(NULL), color(RGB(0, 0, 0)){}
    MY_POINT(double xx, double yy, COLORREF c_color, const char* nname);
    MY_POINT(const MY_POINT& ob);
    ~MY_POINT() 
    { 
        if (name) 
            delete[] name;
        name = NULL;
    }

    MY_POINT& operator=(const MY_POINT& ob);
    void set(double xx, double yy, COLORREF c_color, const char* nname);
    MY_POINT get() { return *this; }

};

class MYDATA_API MY_DATA : public MY_POINT
{
protected:
    MY_POINT* pTab;
    int capacity;
    int last;
public:
    CExcept1App* pExcept;
    MY_DATA(int no_it);
    MY_DATA(const MY_DATA& ob);
    ~MY_DATA() { Free(); }
    int size() { return last; }
    void Free() { if (pTab) delete[] pTab; pTab = NULL; }
    void Init(int no_it);
    void Push(const MY_POINT& tmp);
    int Size() { return last; }
    void clear() { last = 0; }

    MY_POINT& operator [] (const int i) {
        return pTab[i];
    }
    void GetMaxMinCoords(double& max_x, double& min_x, double& max_y, double& min_y);


private:
    MY_POINT* allocTab(MY_POINT* pTab, int n);
};

MyData.cpp:

// MyData.cpp : Defines the initialization routines for the DLL.
//

#include "pch.h"
#include "framework.h"
#include "MyData.h"

#include <iostream>

#ifdef _DEBUG
#define new DEBUG_NEW
#endif

// CMyDataApp

BEGIN_MESSAGE_MAP(CMyDataApp, CWinApp)
END_MESSAGE_MAP()


// CMyDataApp construction

CMyDataApp::CMyDataApp()
{
    // TODO: add construction code here,
    // Place all significant initialization in InitInstance
}


// The one and only CMyDataApp object

CMyDataApp theApp;

// CMyDataApp initialization

BOOL CMyDataApp::InitInstance()
{
    CWinApp::InitInstance();

    return TRUE;
}

MY_POINT::MY_POINT(double xx, double yy, COLORREF c_color, const char* nname = nullptr) : x(xx), y(yy), color(c_color)
{
    try
    {
        if (name)
        {
            name = new char[strlen(nname) + 1];
            strcpy_s(name, strlen(nname) + 1, nname);
        }
    }
    catch (std::bad_alloc)
    {
        //pExcept->PutMessage(1001);
        name = NULL;
    }
}

MY_POINT::MY_POINT(const MY_POINT& ob)
{
    x = ob.x;
    y = ob.y;
    color = ob.color;

    try
    {
        if (ob.name)
        {
            name = new char[strlen(ob.name) + 1];
            strcpy_s(name, strlen(ob.name) + 1, ob.name);
        }
    }
    catch (std::bad_alloc)
    {
        //pExcept->PutMessage(1001);
        name = NULL;
    }
}

MY_POINT& MY_POINT::operator=(const MY_POINT& ob)
{
    if (this == &ob) return *this;

    delete[] name;
    name = NULL;

    x = ob.x;
    y = ob.y;
    color = ob.color;
    try
    {
        if (ob.name)
        {
            name = new char[strlen(ob.name) + 1];
            strcpy_s(name, strlen(ob.name) + 1, ob.name);
        }
    }
    catch (std::bad_alloc)
    {
        //pExcept->PutMessage(1001);
        name = NULL;
    }
    
    return *this;
}

void MY_POINT::set(double xx, double yy, COLORREF c_color, const char* nname)
{
    x = xx;
    y = yy;
    color = c_color;

    delete[] name;
    name = NULL;

    try
    {
        if (name)
        {
            name = new char[strlen(nname) + 1];
            strcpy_s(name, strlen(name) + 1, nname);
        }
    }
    catch (std::bad_alloc)
    {
        //pExcept->PutMessage(1001);
        name = NULL;
    }
}

MY_DATA::MY_DATA(int no_it)
{
    pExcept = GetExceptPtr();
    pTab = NULL;
    Init(no_it);
}

MY_POINT* MY_DATA::allocTab(MY_POINT* pTab, int n)
{
    try
    {
        if (!pTab)
        {
            pTab = new MY_POINT[n];
            capacity = n;
        }
    }
    catch (std::bad_alloc aa)
    {
        //pExcept->PutMessage(1001);
    }
    return pTab;
}
//it's the part of code using pExcept pointer

Except1.h:

// Except1.h : main header file for the Except1 DLL
//

#pragma once

#ifndef __AFXWIN_H__
    #error "include 'pch.h' before including this file for PCH"
#endif

#include "resource.h"       // main symbols

#ifdef EXCEPT1_EXPORT
#define EXCEPT1_API __declspec(dllexport)
#else
#define EXCEPT1_API __declspec(dllimport)
#endif

// CExcept1App
// See Except1.cpp for the implementation of this class
//

#define APP_START_MESSAGE WM_USER+100

enum ITS_APP_MESSAGE
{
    WM_START = APP_START_MESSAGE,
    WM_DIS_MSG,
    WM_CLEAR_OUTPUT,
    WM_DIS_TOTALMES
};

class MY_DATA;

class EXCEPT1_API CExcept1App : public CWinApp
{
public:
    CWnd* ptrWnd;
    MY_DATA* ptrDat;

public:
    CExcept1App();
    void SetWnd(CWnd* ptrwnd, MY_DATA* pdat) { ptrWnd = ptrwnd; ptrDat = pdat; }
    void ResetDat(MY_DATA* pdat) { ptrDat = pdat; }
    void PutMessage(UINT ID_MESSAGE);
    void ClearOutWnd();

// Overrides
public:
    virtual BOOL InitInstance();

    DECLARE_MESSAGE_MAP()
};

extern "C" CExcept1App * PASCAL EXPORT GetExceptPtr();```

GetExceptPtr() is also in Except1.def file:

; Except1.def : Declares the module parameters for the DLL.

LIBRARY

EXPORTS
; Explicit exports can go here
GetExceptPtr



Except1.cpp:
// Except1.cpp : Defines the initialization routines for the DLL.
//

#include "pch.h"
#include "framework.h"
#include "Except1.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#endif

// CExcept1App

BEGIN_MESSAGE_MAP(CExcept1App, CWinApp)
END_MESSAGE_MAP()


// CExcept1App construction

CExcept1App::CExcept1App()
{
    // TODO: add construction code here,
    // Place all significant initialization in InitInstance
    ptrWnd = NULL;
    ptrDat = NULL;
}


// The one and only CExcept1App object

CExcept1App theApp;


// CExcept1App initialization

BOOL CExcept1App::InitInstance()
{
    CWinApp::InitInstance();

    return TRUE;
}


void CExcept1App::PutMessage(UINT ID_Message)
{
    HINSTANCE hInstance = GetModuleHandleA(NULL);
    char str[1024];
    int ret = LoadStringA(hInstance, ID_Message, str, sizeof(str));
    if (ptrWnd)
        ptrWnd->SendMessage(WM_DIS_MSG, (WPARAM)str, (LPARAM)ptrDat);
    else if (!ptrWnd && str[0] == 'E')
    {
        CString sstr(str);
        AfxMessageBox(sstr);
        UINT uExitCode = 0;
        HANDLE hHandle = GetCurrentProcess();
        TerminateProcess(GetCurrentProcess(), uExitCode);
    }
}

void CExcept1App::ClearOutWnd()
{
    if (ptrWnd)
        ptrWnd->SendMessage(WM_CLEAR_OUTPUT, 0, 0);
}

extern "C" CExcept1App * PASCAL EXPORT GetExceptPtr()
{
    AFX_MANAGE_STATE(AfxGetStaticModuleState());
    return &theApp;
}



I've tried to use forward declaration because both Except1 and MyData use their pointers but it didn't solve the problem.
 

New contributor

Damian is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.

Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa Dịch vụ tổ chức sự kiện 5 sao Thông tin về chúng tôi Dịch vụ sinh nhật bé trai Dịch vụ sinh nhật bé gái Sự kiện trọn gói Các tiết mục giải trí Dịch vụ bổ trợ Tiệc cưới sang trọng Dịch vụ khai trương Tư vấn tổ chức sự kiện Hình ảnh sự kiện Cập nhật tin tức Liên hệ ngay Thuê chú hề chuyên nghiệp Tiệc tất niên cho công ty Trang trí tiệc cuối năm Tiệc tất niên độc đáo Sinh nhật bé Hải Đăng Sinh nhật đáng yêu bé Khánh Vân Sinh nhật sang trọng Bích Ngân Tiệc sinh nhật bé Thanh Trang Dịch vụ ông già Noel Xiếc thú vui nhộn Biểu diễn xiếc quay đĩa Dịch vụ tổ chức tiệc uy tín Khám phá dịch vụ của chúng tôi Tiệc sinh nhật cho bé trai Trang trí tiệc cho bé gái Gói sự kiện chuyên nghiệp Chương trình giải trí hấp dẫn Dịch vụ hỗ trợ sự kiện Trang trí tiệc cưới đẹp Khởi đầu thành công với khai trương Chuyên gia tư vấn sự kiện Xem ảnh các sự kiện đẹp Tin mới về sự kiện Kết nối với đội ngũ chuyên gia Chú hề vui nhộn cho tiệc sinh nhật Ý tưởng tiệc cuối năm Tất niên độc đáo Trang trí tiệc hiện đại Tổ chức sinh nhật cho Hải Đăng Sinh nhật độc quyền Khánh Vân Phong cách tiệc Bích Ngân Trang trí tiệc bé Thanh Trang Thuê dịch vụ ông già Noel chuyên nghiệp Xem xiếc khỉ đặc sắc Xiếc quay đĩa thú vị
Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa
Thiết kế website Thiết kế website Thiết kế website Cách kháng tài khoản quảng cáo Mua bán Fanpage Facebook Dịch vụ SEO Tổ chức sinh nhật