Thread: dllimport function not allowed

  1. #1
    UK2
    Join Date
    Sep 2003
    Posts
    112

    dllimport function not allowed

    Hello

    I have downloaded this code from the internet and I am trying to compile it. Howerver, I keep getting these 2 errors which I cannot seem to solve.

    Error C2491 StartNativeProcessing definition of dllimport function not allowed
    Error C2491 StartNativeProcessingWithControlProc definition of dllimport function not allowed.

    Many thanks for any assistance with this code.

    Steve

    Code:
    // The following ifdef block is the standard way of creating macros which make exporting 
    // from a DLL simpler. All files within this DLL are compiled with the NATIVEDLL_EXPORTS
    // symbol defined on the command line. this symbol should not be defined on any project
    // that uses this DLL. This way any other project whose source files include this file see 
    // NATIVEDLL_API functions as being imported from a DLL, whereas this DLL sees symbols
    // defined with this macro as being exported.
    #ifdef NATIVEDLL_EXPORTS
    #define NATIVEDLL_API extern "C" __declspec(dllexport)
    #else
    #define NATIVEDLL_API __declspec(dllimport)
    #endif
    
    // ********************************************************
    // Callback function type definition for a function that is 
    //  called when the processing performed by the native DLL
    //  is complete
    // 
    // Function has no return value & no parameters.
    //  Example: void MyWorkCompleteFunction()
    typedef void (CALLBACK *NATIVEWORKCOMPLETEPROC)();
    
    // Callback function type definition for a function that is
    //  is called within each iteration of the native processing
    //  loop. Native processing will continue until the provided
    //  function returns 0;
    //
    // Function has BOOL return value (int in C#, Integer in VB.NET)
    // Function accepts an LPARAM as a parameter (IntPtr in .NET CF)
    //  The LPARAM parameter passes application defined data
    //  back to the application. The LPARAM is initially provided
    //  to the native DLL on the call to StartNativeProcessingWithControlProc
    //  function.
    typedef BOOL (CALLBACK *NATIVEWORKCONTROLPROC)(LPARAM lParam);
    // ********************************************************
    
    // Initiate processing on a background thread. When processing is complete,
    //  the workCompleteProc callback function is called
    NATIVEDLL_API void StartNativeProcessing(NATIVEWORKCOMPLETEPROC workCompleteProc);
    
    // Initiate processing on a background thread. On each iteration of the
    //  loop, the workControlProc function is called with the lParam passed
    //  as a parameter. The processing on the background thread continues
    //  until the workControlProc callback function returns 0. When processing 
    //  is complete, the workCompleteProc callback function is called
    NATIVEDLL_API void StartNativeProcessingWithControlProc(
    	NATIVEWORKCONTROLPROC workControlProc, LPARAM lParam, NATIVEWORKCOMPLETEPROC workCompleteProc);

    Code:
    // NativeDLL.cpp : Defines the entry point for the DLL application.
    //
    
    #include "stdafx.h"
    #include "NativeDLL.h"
    #include <windows.h>
    #include <commctrl.h>
    
    BOOL APIENTRY DllMain( HANDLE hModule, 
                           DWORD  ul_reason_for_call, 
                           LPVOID lpReserved
    					 )
    {
    	switch (ul_reason_for_call)
    	{
    	case DLL_PROCESS_ATTACH:
    	case DLL_THREAD_ATTACH:
    	case DLL_THREAD_DETACH:
    	case DLL_PROCESS_DETACH:
    		break;
    	}
        return TRUE;
    }
    
    // The reference to the NATIVEWORKCOMPLETEPROC callback function
    NATIVEWORKCOMPLETEPROC g_workCompleteProc = NULL;
    NATIVEWORKCONTROLPROC g_workControlProc = NULL;
    
    // Sleep time to simulate work
    const int workSleepTimeInMilliseconds = 1500;
    
    // Forward declerations
    DWORD WINAPI ThreadFunc(void* pvThreadParam);
    void DoWork();
    
    // Initiate processing on a background thread. When processing is complete,
    //  the workCompleteProc callback function is called
    NATIVEDLL_API  void StartNativeProcessing(NATIVEWORKCOMPLETEPROC workCompleteProc)
    {
    	g_workCompleteProc = workCompleteProc;
    	g_workControlProc = NULL;
    
    	DWORD dwThreadId;
    	CreateThread(0, 0, ThreadFunc, NULL, 0, &dwThreadId);	
    }
    
    // Initiate processing on a background thread. On each iteration of the
    //  loop, the workControlProc function is called with the lParam passed
    //  as a parameter. The processing on the background thread continues
    //  until the workControlProc callback function returns 0. When processing 
    //  is complete, the workCompleteProc callback function is called
    NATIVEDLL_API void StartNativeProcessingWithControlProc(
    	NATIVEWORKCONTROLPROC workControlProc, LPARAM lParam, NATIVEWORKCOMPLETEPROC workCompleteProc)
    {
    	g_workCompleteProc = workCompleteProc;
    	g_workControlProc = workControlProc;
    	
    	DWORD dwThreadId;
    	CreateThread(0, 0, ThreadFunc, (void*)lParam, 0, &dwThreadId);		
    }
    
    // Functioning running on background thread that simulates
    //  some sort of data processing. If only a NATIVEWORKCOMPLETEPROC
    //  callback function is provided, ThreadFunc will go through the loop once
    // If a NATIVEWORKCONTROLPROC callback function is provided, ThreadFunc will loop
    //  until the NATIVEWORKCONTROLPROC callback function returns 0
    DWORD WINAPI ThreadFunc(void* pvThreadParam)
    {
    	int loopControl = 0;
    
    	do
    	{
    		DoWork();
    		if (g_workControlProc != NULL)
    			loopControl = g_workControlProc((LPARAM)pvThreadParam);
    	}
    	while(loopControl != 0);
    
    	if (g_workCompleteProc != NULL)
    		g_workCompleteProc();
    
    	return 0;
    }
    
    // Simulate doing work for sleeping the specified period of time
    void DoWork()
    {
    	Sleep(workSleepTimeInMilliseconds);
    }

  2. #2
    Cat without Hat CornedBee's Avatar
    Join Date
    Apr 2003
    Posts
    8,895
    Remove the NATIVEDLL_API macros from the function definitions.
    All the buzzt!
    CornedBee

    "There is not now, nor has there ever been, nor will there ever be, any programming language in which it is the least bit difficult to write bad code."
    - Flon's Law

  3. #3
    UK2
    Join Date
    Sep 2003
    Posts
    112
    Hello CornedBee,

    Thanks for your the solution. It worked. However, I am not totally sure why. Just have a question for you.

    Why did it work when I removed the NATIVEDLL_API, and what are the macros for?

    Can you explain the code below?

    Many thanks for you help,

    Steve
    Code:
    #ifdef NATIVEDLL_EXPORTS
    #define NATIVEDLL_API extern "C" __declspec(dllexport)
    #else
    #define NATIVEDLL_API __declspec(dllimport)
    #endif

  4. #4
    Cat without Hat CornedBee's Avatar
    Join Date
    Apr 2003
    Posts
    8,895
    Wait, I just realized that my change just masked the error instead of fixing it. I don't have the time right now to explain the problem or the proper fix, but the DLL as it is now is probably unusable.

    Revert the change and add NATIVEDLL_EXPORTS to the project-wide predefined macros.
    All the buzzt!
    CornedBee

    "There is not now, nor has there ever been, nor will there ever be, any programming language in which it is the least bit difficult to write bad code."
    - Flon's Law

  5. #5
    UK2
    Join Date
    Sep 2003
    Posts
    112
    Hello,

    Thanks for the reply

    I understand how the # and preprocessor works.
    However, how do I define NATIVEDLL_EXPORTS, what value do I initially give it.?
    To set this value do I have to go to properties | C/C++ | preprocessor? I have never done anything like this before, so not sure.

    Many thanks for your time,

    Steve

  6. #6
    Cat without Hat CornedBee's Avatar
    Join Date
    Apr 2003
    Posts
    8,895
    Yes, that's where it goes. The value doesn't matter - just add the symbol. It will have the value 1 by default, which is just fine.

    OK, the issue here is the following: the __declspec(dll*) stuff is an MS-specific feature that effectively tells the compiler that this function is to be either exported from the DLL that is currently compiled, or to be imported from a DLL, depending on whether it's dllexport or dllimport, of course.
    The DLL, when being compiled, needs dllexport declarations on all its externally visible functions. A program that uses the DLL needs the dllimport declarations. In order to be able to use the same header file for both, the macro switch was created.
    Because requiring client programs to define symbols just to make the DLL work is not nice, the switch defaults to importing. This means that when compiling the DLL, the switch trigger must be defined. The switch trigger in your case is NATIVEDLL_EXPORTS.
    All the buzzt!
    CornedBee

    "There is not now, nor has there ever been, nor will there ever be, any programming language in which it is the least bit difficult to write bad code."
    - Flon's Law

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Compiling sample DarkGDK Program
    By Phyxashun in forum Game Programming
    Replies: 6
    Last Post: 01-27-2009, 03:07 AM
  2. Seg Fault in Compare Function
    By tytelizgal in forum C Programming
    Replies: 1
    Last Post: 10-25-2008, 03:06 PM
  3. Another syntax error
    By caldeira in forum C Programming
    Replies: 31
    Last Post: 09-05-2008, 01:01 AM
  4. Including lib in a lib
    By bibiteinfo in forum C++ Programming
    Replies: 0
    Last Post: 02-07-2006, 02:28 PM
  5. Game Pointer Trouble?
    By Drahcir in forum C Programming
    Replies: 8
    Last Post: 02-04-2006, 02:53 AM