-
July 10th, 2014, 05:48 AM
#1
Unresolved Externals after using #define DLL extern "C" __declspec(dllexport)
In the calling program, I've got
Code:
Error 1 error LNK2019: unresolved external symbol "public: virtual __thiscall Process::~Process(void)" (??1Process@@UAE@XZ) referenced in function __unwindfunclet$??0Arrivals@@QAE@N@Z$0 E:\Jacky\Documents\Visual Studio 2010\Projects\PerfectSim\PerfectSim\Arrivals.obj PerfectSim
Error 2 error LNK2019: unresolved external symbol "public: __thiscall ExponentialStream::ExponentialStream(double,int,long,long)" (??0ExponentialStream@@QAE@NHJJ@Z) referenced in function "public: __thiscall Arrivals::Arrivals(double)" (??0Arrivals@@QAE@N@Z) E:\Jacky\Documents\Visual Studio 2010\Projects\PerfectSim\PerfectSim\Arrivals.obj PerfectSim
Error 3 error LNK2019: unresolved external symbol "protected: __thiscall Process::Process(void)" (??0Process@@IAE@XZ) referenced in function "public: __thiscall Arrivals::Arrivals(double)" (??0Arrivals@@QAE@N@Z) E:\Jacky\Documents\Visual Studio 2010\Projects\PerfectSim\PerfectSim\Arrivals.obj PerfectSim
Error 4 error LNK2001: unresolved external symbol "public: virtual void __thiscall Process::Suspend(void)" (?Suspend@Process@@UAEXXZ) E:\Jacky\Documents\Visual Studio 2010\Projects\PerfectSim\PerfectSim\Arrivals.obj PerfectSim
Error 5 error LNK2001: unresolved external symbol "public: virtual void __thiscall Process::Resume(void)" (?Resume@Process@@UAEXXZ) E:\Jacky\Documents\Visual Studio 2010\Projects\PerfectSim\PerfectSim\Arrivals.obj PerfectSim
Error 6 error LNK2001: unresolved external symbol "public: virtual long __thiscall Thread::Current_Thread(void)const " (?Current_Thread@Thread@@UBEJXZ) E:\Jacky\Documents\Visual Studio 2010\Projects\PerfectSim\PerfectSim\Arrivals.obj PerfectSim
Error 7 error LNK2001: unresolved external symbol "public: virtual long __thiscall Thread::Identity(void)const " (?Identity@Thread@@UBEJXZ) E:\Jacky\Documents\Visual Studio 2010\Projects\PerfectSim\PerfectSim\Arrivals.obj PerfectSim
Error 8 error LNK2001: unresolved external symbol "public: virtual class std::basic_ostream<char,struct std::char_traits<char> > & __thiscall Thread::print(class std::basic_ostream<char,struct std::char_traits<char> > &)const " (?print@Thread@@UBEAAV?$basic_ostream@DU?$char_traits@D@std@@@std@@AAV23@@Z) E:\Jacky\Documents\Visual Studio 2010\Projects\PerfectSim\PerfectSim\Arrivals.obj PerfectSim
Error 9 error LNK2001: unresolved external symbol "protected: virtual void __thiscall Thread::terminateThread(void)" (?terminateThread@Thread@@MAEXXZ) E:\Jacky\Documents\Visual Studio 2010\Projects\PerfectSim\PerfectSim\Arrivals.obj PerfectSim
Error 10 error LNK2001: unresolved external symbol "public: virtual void __thiscall Process::terminate(void)" (?terminate@Process@@UAEXXZ) E:\Jacky\Documents\Visual Studio 2010\Projects\PerfectSim\PerfectSim\Arrivals.obj PerfectSim
Error 11 error LNK2001: unresolved external symbol "public: virtual void __thiscall Process::reset(void)" (?reset@Process@@UAEXXZ) E:\Jacky\Documents\Visual Studio 2010\Projects\PerfectSim\PerfectSim\Arrivals.obj PerfectSim
Error 12 error LNK2019: unresolved external symbol "public: static void __cdecl Resource::operator delete(void *)" (??3Resource@@SAXPAX@Z) referenced in function "public: virtual void * __thiscall Arrivals::`scalar deleting destructor'(unsigned int)" (??_GArrivals@@UAEPAXI@Z) E:\Jacky\Documents\Visual Studio 2010\Projects\PerfectSim\PerfectSim\Arrivals.obj PerfectSim
Error 13 error LNK2019: unresolved external symbol "protected: void __thiscall Process::Hold(double)" (?Hold@Process@@IAEXN@Z) referenced in function "public: virtual void __thiscall Arrivals::Body(void)" (?Body@Arrivals@@UAEXXZ) E:\Jacky\Documents\Visual Studio 2010\Projects\PerfectSim\PerfectSim\Arrivals.obj PerfectSim
Error 14 error LNK1120: 13 unresolved externals E:\Jacky\Documents\Visual Studio 2010\Projects\PerfectSim\PerfectSim\bin\Debug\\PerfectSim.exe PerfectSim
Are protected members of this class not allowed to be accessed outside the DLL?
I've packed the file named process.cc and process.h into a simudll.lib and a simudll.dll file
I've made one copy of the header files at the perfectsim project. I've changed that to dllimport to no avail
Thanks
Jack
Code:
#define DLL extern "C" __declspec(dllexport)
DLL class Process : public Thread
{
friend Scheduler;
public:
static const double Never;
virtual ~Process ();
/* The following two methods return the current simulation time */
static double CurrentTime (); // C++SIM version
double Time () const; // SIMULA version
double evtime () const; // time at which process is scheduled to be active
/*
* The following method returns a reference to the next process to be run
* by the scheduler *if* this object is active or scheduled to run.
*/
const Process* next_ev () const;
/*
* There are five ways to activate a process:
* 1) at the current simulation time
* 2) before another process,
* 3) after another process,
* 4) at a specified (simulated) time, or
* 5) after a specified (simulated) delay
*/
void Activate ();
void ActivateBefore (Process &);
void ActivateAfter (Process &);
#ifndef __GNUG__
void ActivateAt (double AtTime = CurrentTime(), Boolean prior = FALSE);
void ActivateDelay (double AtTime = CurrentTime(), Boolean prior = FALSE);
#else
void ActivateAt (double AtTime = SimulatedTime, Boolean prior = FALSE);
void ActivateDelay (double AtTime = SimulatedTime, Boolean prior = FALSE);
#endif
/*
* Similarly, there are five ways to reactivate
* Note that if a process is already scheduled, the reactivate
* will simply re-schedule the process.
*/
void ReActivate ();
void ReActivateBefore (Process &);
void ReActivateAfter (Process &);
#ifndef __GNUG__
void ReActivateAt (double AtTime = CurrentTime(), Boolean prior = FALSE);
void ReActivateDelay (double AtTime = CurrentTime(), Boolean prior = FALSE);
#else
void ReActivateAt (double AtTime = SimulatedTime, Boolean prior = FALSE);
void ReActivateDelay (double AtTime = SimulatedTime, Boolean prior = FALSE);
#endif
void Cancel (); // cancels next burst of activity, process becomes idle
Boolean idle () const; // TRUE if process is not awake or not scheduled to wake up
Boolean passivated () const; // returns whether or not the object has been passivated
Boolean terminated () const; // returns whether or not the object has been terminated
virtual void terminate (); // terminate the process - no going back!
static const Process* current (); // returns current process
/*
* The pure virtual function, Body, defines the code that executes in
* the process.
*/
virtual void Body () = 0;
/*
* This method is called whenever a simulation is reset. Default does
* nothing.
*/
virtual void reset ();
static Process* Current;
protected:
Process ();
Process (unsigned long stackSize);
void Hold (double t); // suspend current process for simulated time t
void Passivate (); // suspend current process (i.e., make idle)
void set_evtime (double); // set wakeuptime (used by Scheduler)
// remove from scheduler queue and prepare for passivation
void unschedule ();
private:
Boolean schedule ();
Boolean checkTime (double) const;
double wakeuptime;
Boolean Terminated;
Boolean Passivated;
public:
virtual void Suspend ();
virtual void Resume ();
};
Last edited by lucky6969b; July 10th, 2014 at 06:26 AM.
-
July 10th, 2014, 06:51 AM
#2
Re: Unresolved Externals after using #define DLL extern "C" __declspec(dllexport)
Originally Posted by lucky6969b
Are protected members of this class not allowed to be accessed outside the DLL?
From MSDN:
protected
C++ Specific —>
protected: [member-list]
protected base-class
When preceding a list of class members, the protected keyword specifies that those members are accessible only from member functions and friends of the class and its derived classes. This applies to all members declared up to the next access specifier or the end of the class.
When preceding the name of a base class, the protected keyword specifies that the public and protected members of the base class are protected members of the derived class.
Default access of members in a class is private. Default access of members in a structure or union is public.
Default access of a base class is private for classes and public for structures. Unions cannot have base classes.
Victor Nijegorodov
-
July 10th, 2014, 08:43 AM
#3
Re: Unresolved Externals after using #define DLL extern "C" __declspec(dllexport)
I don't believe you can export a class as an 'extern "c"' ?
I export classes like this
Code:
#define DLL __declspec(dllexport)
class DLL cConsole {
...
All advice is offered in good faith only. All my code is tested (unless stated explicitly otherwise) with the latest version of Microsoft Visual Studio (using the supported features of the latest standard) and is offered as examples only - not as production quality. I cannot offer advice regarding any other c/c++ compiler/IDE or incompatibilities with VS. You are ultimately responsible for the effects of your programs and the integrity of the machines they run on. Anything I post, code snippets, advice, etc is licensed as Public Domain https://creativecommons.org/publicdomain/zero/1.0/ and can be used without reference or acknowledgement. Also note that I only provide advice and guidance via the forums - and not via private messages!
C++23 Compiler: Microsoft VS2022 (17.6.5)
-
July 10th, 2014, 10:47 PM
#4
Re: Unresolved Externals after using #define DLL extern "C" __declspec(dllexport)
I seem to have to dllimport back into my project.
The protected access modifier can make a difference though
I am still checking.
Code:
#ifndef _ARRIVALS_H_
#define _ARRIVALS_H_
//#ifndef PROCESS_H_
# include "Process.h"
//#endif
//#ifndef RANDOM_H_
# include "SimuDLL\Random.h"
//#endif
class Arrivals : public Process {
public:
Arrivals (double);
virtual ~Arrivals ();
virtual void Body ();
private:
ExponentialStream* InterArrivalTime;
};
#endif
These are from the export side
Process.h
Code:
/*
* Copyright (C) 1994-1998,
*
* Department of Computing Science,
* The University,
* Newcastle upon Tyne,
* UK.
*
* $Id: Process.h,v 1.24 1998/08/28 14:19:51 nmcl Exp $
*/
#ifndef PROCESS_H_
#define PROCESS_H_
#ifndef CONFIGURE_H_
# include "Nt_Configure.h"
#endif
#ifndef BOOLEAN_H_
# include "Boolean.h"
#endif
#if defined(DEBUG) && !defined(DEBUG_H_)
# include "Debug.h"
#endif
#ifndef ERROR_H_
# include "Error.h"
#endif
#ifndef THREAD_H_
# include "thread.h"
#endif
class ostream;
/*
* This is the main class for the simulation package. All objects which are to
* possess independent threads of control but which are to be controlled by the
* simulation scheduler MUST be derived from the Process class. The Scheduler,
* which is also an object which possesses an independent thread and which
* exists within the simulation environment, is shown here, but is only derived
* from the Thread_Type class and not Process as it is the central controller
* for the simulation environment and as such runs independently of everything
* else. If debugging is turned on (-DDEBUG added to CFLAGS for the Makefile)
* then the scheduler will print out the current simulation time and other
* information.
*
* Thread_Type is a means of "transparently" changing the thread base class
* implementation.
*/
#ifdef __GNUG__
extern double SimulatedTime;
#endif
#define DLL __declspec(dllexport)
class DLL Scheduler
{
public:
double CurrentTime () const;
void reset () const; // reset the simulation time
static Scheduler& scheduler ();
static void terminate ();
void Suspend ();
void Resume ();
static Boolean simulationStarted ();
static void print (std::ostream&);
protected:
Scheduler ();
virtual ~Scheduler ();
private:
static Scheduler* theScheduler;
static Boolean schedulerRunning;
};
class DLL Process : public Thread
{
friend Scheduler;
public:
static const double Never;
virtual ~Process ();
/* The following two methods return the current simulation time */
static double CurrentTime (); // C++SIM version
double Time () const; // SIMULA version
double evtime () const; // time at which process is scheduled to be active
/*
* The following method returns a reference to the next process to be run
* by the scheduler *if* this object is active or scheduled to run.
*/
const Process* next_ev () const;
/*
* There are five ways to activate a process:
* 1) at the current simulation time
* 2) before another process,
* 3) after another process,
* 4) at a specified (simulated) time, or
* 5) after a specified (simulated) delay
*/
void Activate ();
void ActivateBefore (Process &);
void ActivateAfter (Process &);
#ifndef __GNUG__
void ActivateAt (double AtTime = CurrentTime(), Boolean prior = FALSE);
void ActivateDelay (double AtTime = CurrentTime(), Boolean prior = FALSE);
#else
void ActivateAt (double AtTime = SimulatedTime, Boolean prior = FALSE);
void ActivateDelay (double AtTime = SimulatedTime, Boolean prior = FALSE);
#endif
/*
* Similarly, there are five ways to reactivate
* Note that if a process is already scheduled, the reactivate
* will simply re-schedule the process.
*/
void ReActivate ();
void ReActivateBefore (Process &);
void ReActivateAfter (Process &);
#ifndef __GNUG__
void ReActivateAt (double AtTime = CurrentTime(), Boolean prior = FALSE);
void ReActivateDelay (double AtTime = CurrentTime(), Boolean prior = FALSE);
#else
void ReActivateAt (double AtTime = SimulatedTime, Boolean prior = FALSE);
void ReActivateDelay (double AtTime = SimulatedTime, Boolean prior = FALSE);
#endif
void Cancel (); // cancels next burst of activity, process becomes idle
Boolean idle () const; // TRUE if process is not awake or not scheduled to wake up
Boolean passivated () const; // returns whether or not the object has been passivated
Boolean terminated () const; // returns whether or not the object has been terminated
virtual void terminate (); // terminate the process - no going back!
static const Process* current (); // returns current process
/*
* The pure virtual function, Body, defines the code that executes in
* the process.
*/
virtual void Body () = 0;
/*
* This method is called whenever a simulation is reset. Default does
* nothing.
*/
virtual void reset ();
static Process* Current;
protected:
Process ();
Process (unsigned long stackSize);
void Hold (double t); // suspend current process for simulated time t
void Passivate (); // suspend current process (i.e., make idle)
void set_evtime (double); // set wakeuptime (used by Scheduler)
// remove from scheduler queue and prepare for passivation
void unschedule ();
private:
Boolean schedule ();
Boolean checkTime (double) const;
double wakeuptime;
Boolean Terminated;
Boolean Passivated;
public:
virtual void Suspend ();
virtual void Resume ();
};
#include "Process.n"
#endif // PROCESS_H
Process.cc
Code:
/*
* Copyright (C) 1991-1997, 1998,
*
* Department of Computing Science,
* The University,
* Newcastle upon Tyne,
* UK.
*
* $Id: Process.cc,v 1.39 1998/10/05 09:03:11 nmcl Exp $
*/
#ifndef CONFIGURE_H_
# include "Nt_Configure.h"
#endif
#ifndef PROCESS_H_
# include "Process.h"
#endif
#ifdef ProcessList_Queue
# ifndef PROCESSLIST_H_
# include "ProcessList.h"
# endif
#endif
#ifdef ProcessHeap_Queue
# ifndef PROCESSHEAP_H_
# include "ProcessHeap.h"
# endif
#endif
#ifdef Calendar_Queue
# ifndef CALENDAR_H_
# include "Calendar.h"
# endif
#endif
#ifdef HashedList_Queue
# ifndef HASHEDLIST_H_
# include "HashedList.h"
# endif
#endif
#ifndef __GNUG__
static double SimulatedTime = 0.0;
#else
double SimulatedTime = 0.0;
#endif
#ifndef TESTQUEUE
static Queue_Type ReadyQueue; // Queue_Type is replaced by cpp
#else
Queue_Type ReadyQueue;
#endif
static Mutex* _theMutex = Mutex::create();
Scheduler* Scheduler::theScheduler = (Scheduler*) 0;
Boolean Scheduler::schedulerRunning = FALSE;
Process* Process::Current = (Process*) 0;
const double Process::Never = -1; // Process will never awaken.
/*
* Note: unlike in SIMULA, an active process is removed from the simulation
* queue prior to being activated.
*/
//
// Class Scheduler
//
// scheduler is just an object, with no associated thread.
Scheduler::Scheduler ()
{
}
Scheduler::~Scheduler ()
{
}
/*
* This routine resets the simulation time to zero and removes all
* entries from the scheduler queue (as their times may no longer
* be valid). Such entries are suspended as though Cancel had been
* called on them by a "user" process.
*
* Note: if this is to be used to reset the simulation environment
* for another "run" then some means of re-initializing these queue
* entries will be required. This is up to the user to provide and
* invoke prior to their being used again.
*/
void Scheduler::reset () const
{
Process* tmp = (Process*) 0;
do
{
tmp = ReadyQueue.Remove();
if (tmp)
{
tmp->Cancel();
tmp->reset(); // call user-definable reset routine.
}
} while (tmp);
SimulatedTime = 0.0;
}
double Scheduler::CurrentTime () const { return SimulatedTime; }
void Scheduler::print (std::ostream& strm)
{
strm << "Scheduler queue:\n" << std::endl;
ReadyQueue.print(strm);
strm << "End of scheduler queue." << std::endl;
}
//
// Class Process
//
/*
* Before this process is deleted, make sure it
* is removed from the queue, or we could have
* problems with pointer dereferencing!
*/
Process::~Process ()
{
/*
* We don't call Cancel of terminate here since they will
* attempt to suspend this process if it is running, and
* we do not want that to occur - garbage could quickly
* build up. So, we let the destructor run to completion
* which will implicitly suspend the process anyway, and
* let the thread specific destructor then decide whether
* it needs to do anything specific (e.g., reactivate the
* scheduler) before it finishes.
*/
if (!Terminated)
{
Terminated = TRUE;
Passivated = TRUE;
unschedule(); // remove from scheduler queue
wakeuptime = Process::Never;
if (this == Process::Current)
{
schedule();
_theMutex->unlock();
}
}
}
double Process::CurrentTime () { return SimulatedTime; }
void Process::set_evtime (double time)
{
if (!idle()) // error if we are not scheduled for activation
{
if (time >= Process::CurrentTime())
wakeuptime = time;
else
error_stream << WARNING
<< "Process::set_evtime - time " << time
<< " invalid" << std::endl;
}
else
error_stream << WARNING
<< "Process::set_evtime called for idle process." << std::endl;
}
// return process to be activated after this process.
const Process* Process::next_ev () const
{
return ((!idle()) ? ReadyQueue.getNext(this) : (Process*) 0);
}
/*
* These routines are slightly different to the SIMULA
* equivalents in that a process must be given, and that
* process must be scheduled. Complete compatibility
* may be provided in future releases.
*/
void Process::ActivateBefore (Process &p)
{
// No op if already scheduled
if (Terminated || !idle()) return;
Passivated = FALSE;
if (ReadyQueue.InsertBefore(*this, p))
wakeuptime = p.wakeuptime;
else
error_stream << WARNING << "ActivateBefore failed because 'before' process is not scheduled" << std::endl;
}
void Process::ActivateAfter (Process &p)
{
// No op if already scheduled
if (Terminated || !idle()) return;
Passivated = FALSE;
if (ReadyQueue.InsertAfter(*this, p))
wakeuptime = p.wakeuptime;
else
error_stream << WARNING << "ActivateAfter failed because 'after' process is not scheduled" << std::endl;
}
/*
* These routines differ from their SIMULA counterparts in
* that a negative AtTime is considered an error, and will
* not cause the process to be activated at the current time.
* This may change in a future release, when we may provide
* a "SIMULA compatibility" mode.
*/
void Process::ActivateAt (double AtTime, Boolean prior)
{
// No op if already scheduled
if ((AtTime < Process::CurrentTime()) || Terminated || !idle()) return;
Passivated = FALSE;
wakeuptime = AtTime;
ReadyQueue.Insert(*this, prior);
}
void Process::ActivateDelay (double Delay, Boolean prior)
{
// No op if already scheduled
if (!checkTime(Delay) || Terminated || !idle()) return;
Passivated = FALSE;
wakeuptime = SimulatedTime + Delay;
ReadyQueue.Insert(*this, prior);
}
void Process::Activate ()
{
// No op if already scheduled
if (Terminated || !idle()) return;
Passivated = FALSE;
wakeuptime = CurrentTime();
ReadyQueue.Insert(*this, TRUE);
}
/*
* Similarly, there are four ways to reactivate
* Note that if a process is already scheduled, the reactivate
* will simply re-schedule the process.
*/
void Process::ReActivateBefore (Process &p)
{
if (Terminated) return;
unschedule();
ActivateBefore(p);
if (Process::Current == this)
Suspend();
}
void Process::ReActivateAfter (Process &p)
{
if (Terminated) return;
unschedule();
ActivateAfter(p);
if (Process::Current == this)
Suspend();
}
void Process::ReActivateAt (double AtTime, Boolean prior)
{
if (Terminated) return;
unschedule();
ActivateAt(AtTime, prior);
if (Process::Current == this)
Suspend();
}
void Process::ReActivateDelay (double Delay, Boolean prior)
{
if (Terminated) return;
unschedule();
ActivateDelay(Delay, prior);
if (Process::Current == this)
Suspend();
}
void Process::ReActivate ()
{
if (Terminated) return;
unschedule();
Activate();
if (Process::Current == this)
Suspend();
}
Boolean Process::schedule ()
{
if (Scheduler::simulationStarted())
{
Boolean doSuspend = TRUE;
Process::Current = ReadyQueue.Remove();
if (Process::Current == (Process*) 0) // all done
{
std::cout << "Scheduler queue is empty. Simulation ending" << std::endl;
Thread::Exit();
}
if (Process::Current->evtime() < 0)
{
error_stream << WARNING << "Scheduler Error: Process WakeupTime "
<< Process::Current->evtime() << " invalid.\n";
}
else
SimulatedTime = Process::Current->evtime();
#ifdef DEBUG
debug_stream << FUNCTIONS << FAC_SCHEDULER << VIS_PUBLIC;
debug_stream << "Simulated time is now " << SimulatedTime << std::endl;
#endif
if (Process::Current != this)
Process::Current->Resume();
else
doSuspend = FALSE;
return doSuspend;
}
else
return FALSE;
}
// only called if process is running or on queue to be run
void Process::unschedule ()
{
if (!idle())
{
if (this != Process::Current)
(void) ReadyQueue.Remove(this); // remove from queue
wakeuptime = Process::Never;
Passivated = TRUE;
}
}
/*
* Cancels next burst of activity, process becomes idle.
* If the process is currently active then it is suspended,
* and a reschedule is performed.
*/
void Process::Cancel ()
{
/*
* We must suspend this process either by removing it from
* the scheduler queue (if it is already suspended) or by
* calling suspend directly.
*/
if (!idle()) // process is running or on queue to be run
{
unschedule(); // remove from queue
if (this == Process::Current) // currently active, so simply suspend
Suspend();
}
}
void Process::reset ()
{
#ifdef DEBUG
error_stream << WARNING << "Reset of process called." << std::endl;
#endif
}
Process::Process ()
: wakeuptime(Process::Never),
Terminated(FALSE),
Passivated(TRUE)
{
}
Process::Process (unsigned long stackSize)
: Thread(stackSize),
wakeuptime(Process::Never),
Terminated(FALSE),
Passivated(TRUE)
{
}
// suspend current process for simulated time t
void Process::Hold (double t)
{
if (checkTime(t))
{
if ((this == Process::Current) || (!Process::Current))
{
wakeuptime = Process::Never;
ActivateDelay(t);
Suspend();
}
else
error_stream << WARNING
<< "Process::Hold - can only be applied to active object."
<< std::endl;
}
else
error_stream << WARNING << "Process::Hold - time " << t
<< " invalid." << std::endl;
}
// this works on active and scheduled processes
void Process::terminate ()
{
if (!Terminated)
{
if (this != Process::Current)
unschedule();
/*
* Don't set these until after we are finished
* with them!
*/
Terminated = Passivated = TRUE;
wakeuptime = Process::Never;
if (this == Process::Current)
{
schedule();
_theMutex->unlock();
}
terminateThread();
}
}
/*
* We add these routines because we may need to do some
* Process specific manipulations prior to calling the
* thread specific implementations.
*/
void Process::Suspend ()
{
if (schedule())
{
_theMutex->unlock();
Thread::Suspend();
_theMutex->lock();
}
}
/*
* Make sure that Process::Current is always valid.
*/
void Process::Resume ()
{
if (Process::Current == (Process*) 0)
{
Process::Current = this;
wakeuptime = CurrentTime();
}
if (!Terminated)
Thread::Resume();
}
#ifdef NO_INLINES
# define PROCESS_CC_
# include "Process.n"
# undef PROCESS_CC_
#endif
Isn't this the calling convention problem? I've checked, it is C call in SimuDLL and C call in PerfectSim?!
Code:
Error 1 error LNK2019: unresolved external symbol "__declspec(dllimport) public: virtual __thiscall Process::~Process(void)" (__imp_??1Process@@UAE@XZ) referenced in function __unwindfunclet$??0Arrivals@@QAE@N@Z$0 E:\Jacky\Documents\Visual Studio 2010\Projects\PerfectSim\PerfectSim\Arrivals.obj PerfectSim
Error 2 error LNK2019: unresolved external symbol "__declspec(dllimport) public: __thiscall ExponentialStream::ExponentialStream(double,int,long,long)" (__imp_??0ExponentialStream@@QAE@NHJJ@Z) referenced in function "public: __thiscall Arrivals::Arrivals(double)" (??0Arrivals@@QAE@N@Z) E:\Jacky\Documents\Visual Studio 2010\Projects\PerfectSim\PerfectSim\Arrivals.obj PerfectSim
Error 3 error LNK2019: unresolved external symbol "__declspec(dllimport) protected: __thiscall Process::Process(void)" (__imp_??0Process@@IAE@XZ) referenced in function "public: __thiscall Arrivals::Arrivals(double)" (??0Arrivals@@QAE@N@Z) E:\Jacky\Documents\Visual Studio 2010\Projects\PerfectSim\PerfectSim\Arrivals.obj PerfectSim
Error 4 error LNK2001: unresolved external symbol "public: virtual void __thiscall Process::Suspend(void)" (?Suspend@Process@@UAEXXZ) E:\Jacky\Documents\Visual Studio 2010\Projects\PerfectSim\PerfectSim\Arrivals.obj PerfectSim
... more
Thanks
Jack
Last edited by lucky6969b; July 11th, 2014 at 12:01 AM.
-
July 11th, 2014, 12:35 AM
#5
Re: Unresolved Externals after using #define DLL extern "C" __declspec(dllexport)
I really hate the idea of C++ class exporting from DLLs. First of all it tends to depend on C++ flavor, as well as C++ runtime version. My choice always is exporting interfaces but not classes. Besides, you are automatically appear to be safe of lots of other tiny details as what to do with class private/protected parts, or safe object destruction, etc.
Interface goes along with dynamic DLL loading/unloading just perfect. Yeah, you need to contemplate on interface design a little bit longer, but I take this for a merit.
Best regards,
Igor
-
July 11th, 2014, 04:16 AM
#6
Re: Unresolved Externals after using #define DLL extern "C" __declspec(dllexport)
You are linking with the correct lib file for the dll?
What does dumpbin of the .lib file for the dll show for exports?
All advice is offered in good faith only. All my code is tested (unless stated explicitly otherwise) with the latest version of Microsoft Visual Studio (using the supported features of the latest standard) and is offered as examples only - not as production quality. I cannot offer advice regarding any other c/c++ compiler/IDE or incompatibilities with VS. You are ultimately responsible for the effects of your programs and the integrity of the machines they run on. Anything I post, code snippets, advice, etc is licensed as Public Domain https://creativecommons.org/publicdomain/zero/1.0/ and can be used without reference or acknowledgement. Also note that I only provide advice and guidance via the forums - and not via private messages!
C++23 Compiler: Microsoft VS2022 (17.6.5)
-
July 11th, 2014, 05:38 AM
#7
Re: Unresolved Externals after using #define DLL extern "C" __declspec(dllexport)
Here is the dump, Excuse me because I am not quite familiar with the name decoration and mangling stuff.
Indeed, the destructor seems not to exist.....
Thanks
Jack
Code:
Microsoft (R) COFF/PE Dumper Version 10.00.40219.01
Copyright (C) Microsoft Corporation. All rights reserved.
Dump of file SimuDLL.lib
File Type: LIBRARY
Archive member name at 8: /
53BF6C8B time/date Fri Jul 11 12:48:11 2014
uid
gid
0 mode
1983 size
correct header end
189 public symbols
33B6 __IMPORT_DESCRIPTOR_SimuDLL
35E0 __NULL_IMPORT_DESCRIPTOR
3716 SimuDLL_NULL_THUNK_DATA
3FEC ??0Scheduler@@QAE@ABV0@@Z
3FEC __imp_??0Scheduler@@QAE@ABV0@@Z
4C88 __imp_??_7Scheduler@@6B@
45AA ??4Scheduler@@QAEAAV0@ABV0@@Z
45AA __imp_??4Scheduler@@QAEAAV0@ABV0@@Z
3E16 ??0Process@@QAE@ABV0@@Z
3E16 __imp_??0Process@@QAE@ABV0@@Z
4BA8 __imp_??_7Process@@6B@
44B4 ??4Process@@QAEAAV0@ABV0@@Z
44B4 __imp_??4Process@@QAEAAV0@ABV0@@Z
6082 ?simulationStarted@Scheduler@@SA_NXZ
6082 __imp_?simulationStarted@Scheduler@@SA_NXZ
585A ?Suspend@Scheduler@@QAEXXZ
585A __imp_?Suspend@Scheduler@@QAEXXZ
576E ?Resume@Scheduler@@QAEXXZ
576E __imp_?Resume@Scheduler@@QAEXXZ
5F0E ?scheduler@Scheduler@@SAAAV1@XZ
5F0E __imp_?scheduler@Scheduler@@SAAAV1@XZ
617C ?terminate@Scheduler@@SAXXZ
617C __imp_?terminate@Scheduler@@SAXXZ
5B2C ?evtime@Process@@QBENXZ
5B2C __imp_?evtime@Process@@QBENXZ
61F4 ?terminated@Process@@QBE_NXZ
61F4 __imp_?terminated@Process@@QBE_NXZ
5C8E ?passivated@Process@@QBE_NXZ
5C8E __imp_?passivated@Process@@QBE_NXZ
58D2 ?Time@Process@@QBENXZ
58D2 __imp_?Time@Process@@QBENXZ
59BE ?checkTime@Process@@ABE_NN@Z
59BE __imp_?checkTime@Process@@ABE_NN@Z
5AB4 ?current@Process@@SAPBV1@XZ
5AB4 __imp_?current@Process@@SAPBV1@XZ
5BA0 ?idle@Process@@QBE_NXZ
5BA0 __imp_?idle@Process@@QBE_NXZ
5406 ?Passivate@Process@@IAEXXZ
5406 __imp_?Passivate@Process@@IAEXXZ
626E __imp_?theScheduler@Scheduler@@0PAV1@A
5F8A __imp_?schedulerRunning@Scheduler@@0_NA
50C8 __imp_?Current@Process@@2PAV1@A
5396 __imp_?Never@Process@@2NB
41C6 ??1Scheduler@@MAE@XZ
41C6 __imp_??1Scheduler@@MAE@XZ
57E4 ?Suspend@Process@@UAEXXZ
57E4 __imp_?Suspend@Process@@UAEXXZ
56FA ?Resume@Process@@UAEXXZ
56FA __imp_?Resume@Process@@UAEXXZ
6104 ?terminate@Process@@UAEXXZ
6104 __imp_?terminate@Process@@UAEXXZ
5DAC ?reset@Process@@UAEXXZ
5DAC __imp_?reset@Process@@UAEXXZ
4156 ??1Process@@UAE@XZ
4156 __imp_??1Process@@UAE@XZ
3F7A ??0Scheduler@@IAE@XZ
3F7A __imp_??0Scheduler@@IAE@XZ
513E ?CurrentTime@Process@@SANXZ
513E __imp_?CurrentTime@Process@@SANXZ
5054 ?Cancel@Process@@QAEXXZ
5054 __imp_?Cancel@Process@@QAEXXZ
5E20 ?reset@Scheduler@@QBEXXZ
5E20 __imp_?reset@Scheduler@@QBEXXZ
51B6 ?CurrentTime@Scheduler@@QBENXZ
51B6 __imp_?CurrentTime@Scheduler@@QBENXZ
5D08 ?print@Scheduler@@SAXAAV?$basic_ostream@DU?$char_traits@D@std@@@std@@@Z
5D08 __imp_?print@Scheduler@@SAXAAV?$basic_ostream@DU?$char_traits@D@std@@@std@@@Z
5E96 ?schedule@Process@@AAE_NXZ
5E96 __imp_?schedule@Process@@AAE_NXZ
62EC ?unschedule@Process@@IAEXXZ
62EC __imp_?unschedule@Process@@IAEXXZ
6008 ?set_evtime@Process@@IAEXN@Z
6008 __imp_?set_evtime@Process@@IAEXN@Z
5C14 ?next_ev@Process@@QBEPBV1@XZ
5C14 __imp_?next_ev@Process@@QBEPBV1@XZ
4F54 ?ActivateBefore@Process@@QAEXAAV1@@Z
4F54 __imp_?ActivateBefore@Process@@QAEXAAV1@@Z
4E58 ?ActivateAfter@Process@@QAEXAAV1@@Z
4E58 __imp_?ActivateAfter@Process@@QAEXAAV1@@Z
4ED8 ?ActivateAt@Process@@QAEXN_N@Z
4ED8 __imp_?ActivateAt@Process@@QAEXN_N@Z
4FD6 ?ActivateDelay@Process@@QAEXN_N@Z
4FD6 __imp_?ActivateDelay@Process@@QAEXN_N@Z
4DE2 ?Activate@Process@@QAEXXZ
4DE2 __imp_?Activate@Process@@QAEXXZ
55F6 ?ReActivateBefore@Process@@QAEXAAV1@@Z
55F6 __imp_?ReActivateBefore@Process@@QAEXAAV1@@Z
54F6 ?ReActivateAfter@Process@@QAEXAAV1@@Z
54F6 __imp_?ReActivateAfter@Process@@QAEXAAV1@@Z
5578 ?ReActivateAt@Process@@QAEXN_N@Z
5578 __imp_?ReActivateAt@Process@@QAEXN_N@Z
567A ?ReActivateDelay@Process@@QAEXN_N@Z
567A __imp_?ReActivateDelay@Process@@QAEXN_N@Z
547E ?ReActivate@Process@@QAEXXZ
547E __imp_?ReActivate@Process@@QAEXXZ
3DA6 ??0Process@@IAE@XZ
3DA6 __imp_??0Process@@IAE@XZ
3D36 ??0Process@@IAE@K@Z
3D36 __imp_??0Process@@IAE@K@Z
52AA ?Hold@Process@@IAEXN@Z
52AA __imp_?Hold@Process@@IAEXN@Z
3F00 ??0RandomStream@@QAE@ABV0@@Z
3F00 __imp_??0RandomStream@@QAE@ABV0@@Z
4C16 __imp_??_7RandomStream@@6B@
452C ??4RandomStream@@QAEAAV0@ABV0@@Z
452C __imp_??4RandomStream@@QAEAAV0@ABV0@@Z
4D6C ??_FRandomStream@@QAEXXZ
4D6C __imp_??_FRandomStream@@QAEXXZ
3E8A ??0RandomStream@@IAE@JJ@Z
3E8A __imp_??0RandomStream@@IAE@JJ@Z
4062 ??0UniformStream@@QAE@ABV0@@Z
4062 __imp_??0UniformStream@@QAE@ABV0@@Z
4CF8 __imp_??_7UniformStream@@6B@
48F0 ??RUniformStream@@UAENXZ
48F0 __imp_??RUniformStream@@UAENXZ
3868 ??0Draw@@QAE@ABV0@@Z
3868 __imp_??0Draw@@QAE@ABV0@@Z
4966 __imp_??_7Draw@@6B@
46A2 ??RDraw@@UAE_NXZ
46A2 __imp_??RDraw@@UAE_NXZ
3A3E ??0ExponentialStream@@QAE@ABV0@@Z
3A3E __imp_??0ExponentialStream@@QAE@ABV0@@Z
4A42 __imp_??_7ExponentialStream@@6B@
4784 ??RExponentialStream@@UAENXZ
4784 __imp_??RExponentialStream@@UAENXZ
394A ??0ErlangStream@@QAE@ABV0@@Z
394A __imp_??0ErlangStream@@QAE@ABV0@@Z
49D0 __imp_??_7ErlangStream@@6B@
4710 ??RErlangStream@@UAENXZ
4710 __imp_??RErlangStream@@UAENXZ
3B3A ??0HyperExponentialStream@@QAE@ABV0@@Z
3B3A __imp_??0HyperExponentialStream@@QAE@ABV0@@Z
4ABA __imp_??_7HyperExponentialStream@@6B@
47FE ??RHyperExponentialStream@@UAENXZ
47FE __imp_??RHyperExponentialStream@@UAENXZ
3C42 ??0NormalStream@@QAE@ABV0@@Z
3C42 __imp_??0NormalStream@@QAE@ABV0@@Z
4B36 __imp_??_7NormalStream@@6B@
487C ??RNormalStream@@UAENXZ
487C __imp_??RNormalStream@@UAENXZ
531E ?MGen@RandomStream@@AAENXZ
531E __imp_?MGen@RandomStream@@AAENXZ
5944 ?Uniform@RandomStream@@IAENXZ
5944 __imp_?Uniform@RandomStream@@IAENXZ
5232 ?Error@RandomStream@@QAENXZ
5232 __imp_?Error@RandomStream@@QAENXZ
5A38 ?copy@RandomStream@@IAEXABV1@@Z
5A38 __imp_?copy@RandomStream@@IAEXABV1@@Z
40DC ??0UniformStream@@QAE@NNHJJ@Z
40DC __imp_??0UniformStream@@QAE@NNHJJ@Z
4624 ??4UniformStream@@QAEAAV0@ABV0@@Z
4624 __imp_??4UniformStream@@QAEAAV0@ABV0@@Z
38DA ??0Draw@@QAE@NHJJ@Z
38DA __imp_??0Draw@@QAE@NHJJ@Z
4238 ??4Draw@@QAEAAV0@ABV0@@Z
4238 __imp_??4Draw@@QAEAAV0@ABV0@@Z
3ABC ??0ExponentialStream@@QAE@NHJJ@Z
3ABC __imp_??0ExponentialStream@@QAE@NHJJ@Z
432C ??4ExponentialStream@@QAEAAV0@ABV0@@Z
432C __imp_??4ExponentialStream@@QAEAAV0@ABV0@@Z
39C4 ??0ErlangStream@@QAE@NNHJJ@Z
39C4 __imp_??0ErlangStream@@QAE@NNHJJ@Z
42AE ??4ErlangStream@@QAEAAV0@ABV0@@Z
42AE __imp_??4ErlangStream@@QAEAAV0@ABV0@@Z
3BBE ??0HyperExponentialStream@@QAE@NNHJJ@Z
3BBE __imp_??0HyperExponentialStream@@QAE@NNHJJ@Z
43AE ??4HyperExponentialStream@@QAEAAV0@ABV0@@Z
43AE __imp_??4HyperExponentialStream@@QAEAAV0@ABV0@@Z
3CBC ??0NormalStream@@QAE@NNHJJ@Z
3CBC __imp_??0NormalStream@@QAE@NNHJJ@Z
4436 ??4NormalStream@@QAEAAV0@ABV0@@Z
4436 __imp_??4NormalStream@@QAEAAV0@ABV0@@Z
65E8 __imp__optarg_a
664E __imp__optarg_w
6718 __imp__optind
66B4 __imp__opterr
677C __imp__optopt
6364 __imp__getopt_a
6364 _getopt_a
63CA __imp__getopt_long_a
63CA _getopt_long_a
6436 __imp__getopt_long_only_a
6436 _getopt_long_only_a
6582 __imp__getopt_w
6582 _getopt_w
6516 __imp__getopt_long_w
6516 _getopt_long_w
64A6 __imp__getopt_long_only_w
64A6 _getopt_long_only_w
Last edited by lucky6969b; July 11th, 2014 at 05:50 AM.
-
July 11th, 2014, 05:46 AM
#8
Re: Unresolved Externals after using #define DLL extern "C" __declspec(dllexport)
Looking at one entry,
From SimuDLL.lib
Code:
4156 ??1Process@@UAE@XZ
4156 __imp_??1Process@@UAE@XZ
From linker error
Code:
(??1Process@@UAE@XZ)
Are you sure you are correctly linking with SimuDLL.lib?
All advice is offered in good faith only. All my code is tested (unless stated explicitly otherwise) with the latest version of Microsoft Visual Studio (using the supported features of the latest standard) and is offered as examples only - not as production quality. I cannot offer advice regarding any other c/c++ compiler/IDE or incompatibilities with VS. You are ultimately responsible for the effects of your programs and the integrity of the machines they run on. Anything I post, code snippets, advice, etc is licensed as Public Domain https://creativecommons.org/publicdomain/zero/1.0/ and can be used without reference or acknowledgement. Also note that I only provide advice and guidance via the forums - and not via private messages!
C++23 Compiler: Microsoft VS2022 (17.6.5)
-
July 11th, 2014, 06:05 AM
#9
Re: Unresolved Externals after using #define DLL extern "C" __declspec(dllexport)
I think I messed up the different variations of the same library, I cleaned everything up, and it links.
However, I am dealing with exportation of static members of the class.
Update:
Yeah, it works now....
Thanks
Jack
Last edited by lucky6969b; July 11th, 2014 at 06:18 AM.
Posting Permissions
- You may not post new threads
- You may not post replies
- You may not post attachments
- You may not edit your posts
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|