CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Results 1 to 9 of 9
  1. #1
    Join Date
    Dec 2010
    Posts
    907

    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.

  2. #2
    VictorN's Avatar
    VictorN is offline Super Moderator Power Poster
    Join Date
    Jan 2003
    Location
    Hanover Germany
    Posts
    20,396

    Re: Unresolved Externals after using #define DLL extern "C" __declspec(dllexport)

    Quote Originally Posted by lucky6969b View Post
    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

  3. #3
    2kaud's Avatar
    2kaud is offline Super Moderator Power Poster
    Join Date
    Dec 2012
    Location
    England
    Posts
    7,824

    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)

  4. #4
    Join Date
    Dec 2010
    Posts
    907

    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.

  5. #5
    Join Date
    Nov 2000
    Location
    Voronezh, Russia
    Posts
    6,620

    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

  6. #6
    2kaud's Avatar
    2kaud is offline Super Moderator Power Poster
    Join Date
    Dec 2012
    Location
    England
    Posts
    7,824

    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)

  7. #7
    Join Date
    Dec 2010
    Posts
    907

    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.

  8. #8
    2kaud's Avatar
    2kaud is offline Super Moderator Power Poster
    Join Date
    Dec 2012
    Location
    England
    Posts
    7,824

    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)

  9. #9
    Join Date
    Dec 2010
    Posts
    907

    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
  •  





Click Here to Expand Forum to Full Width

Featured