Thread: Problem with accessing DLL functions

  1. #1
    Registered User
    Join Date
    Feb 2012
    Posts
    25

    Problem with accessing DLL functions

    Hi!

    I’m attempting to translate currently-functional c-mex s-function code (from the Matlab platform) into regular C code. In that c-mex s-function code, the following sequence works to access the functions within my .dll:

    Code:
     
    HINSTANCE dll;
     
    typedef bool (*fcn1WrapperPointer)(int numInputs, int numOutputs, char *fileName); 
    fcn1WrapperPointer fcn1Wrapper;   /* Pointer to "fcn1Wrapper" function within the .dll */
     
     
    mdlStart(…){   /* equivalent of main() in C */ 
     
    dll = LoadLibrary("myLibrary.dll");
     
    fcn1Wrapper = (fcn1WrapperPointer)GetProcAddress(dll, "fcn1Wrapper");
     
    /* call fcn1() */
    fcn1Wrapper(…); 
     
    }
    However, in my C code, when I place the following declarations in my global workspace:


    Code:
     
    line 31: HINSTANCE dll;  /* mydll.dll exports a function called _addInts */ 
     
    line 33: extern "C" __declspec(dll) bool (*fcn1WrapperPointer)(int numInputs, int numOutputs, char *fileName);
     
    main(){
    dll = LoadLibrary("myLibrary.dll");
    }
    … I get the compiler (gcc) error:

    line 33: error: expected identified or '(' before string constant


    I’ve searched around for solutions to this error, and it seems that there are numerous possible causes; however, none of the suggested solutions has resolved this error.

    In case it’s relevant, the .dll was compiled using Visual C++ 2008 Express Edition, and again, my c-mex s-function code has had no problems with calling this .dll’s functions. I believe that I've declared all of the necessary headers.

    Any suggestions? Thanks in advance for your advice.

  2. #2

  3. #3
    Registered User
    Join Date
    Feb 2012
    Posts
    25
    Thanks for your suggestion, Codeplug. I tried it out, but unfortunately, I still receive the same exact compiler error ("expected identified or '(' before string constant"). Any other suggestions from anyone? Thanks!

  4. #4
    Registered User
    Join Date
    May 2012
    Location
    Arizona, USA
    Posts
    945
    extern "C" is not valid syntax in C. Are you trying to compile this as C or as C++? Also keep in mind that you're posting in a C sub-forum.

  5. #5
    Registered User
    Join Date
    Feb 2012
    Posts
    25
    Thanks for your clarification, christop. I had suspected that "extern C" isn't valid C syntax, but am not sure how to proceed. My source code is written in C++, compiled into a .dll using Visual Studio 2008 Express Edition, and I'm trying to access the functions within this .dll within my C code, compiled using the gcc via Cygwin.


    I've found suggestions such as this:

    How can I create a C++ function f(int,char,float) that is callable by my C code?, C++ FAQ

    The C++ source code that I'm working with has functions defined similarly to this:

    Code:
    extern "C" __declspec(dllexport) int sum(int a, int b, char *c)
    {
    	ofstream out("sumOut.txt");
    	out << "Hello World!" << endl;
    	out << c << endl;
    	return a+b;
    }
    ... and I understand that the C++ source code I'm working with does contain the __declspec(dllexport) phrase, while the example C++ code in that link doesn't; possibly that's why no permutation of ideas that I've tried, to access the .dll in my C code, has worked (e.g. the link above's suggested syntax of just using the function name within my code, using my functional c-mex s-function code to access the .dll & use its functions, removing "extern "C"" or "__declspec(dll)", etc. etc.).

    Is it possible that my entire C++ source code will need to be overhauled now that I want to access these C++ functions within C, instead of a c-mex s-function (where they worked fine)? Or, is there some other technique that will allow me to call my existing C++ .dll from my C code? Thanks.

  6. #6
    Algorithm Dissector iMalc's Avatar
    Join Date
    Dec 2005
    Location
    New Zealand
    Posts
    6,318
    Just remove the extern "C". This is already C code, so you shouldn't be telling the C compiler that it's C code.
    My homepage
    Advice: Take only as directed - If symptoms persist, please see your debugger

    Linus Torvalds: "But it clearly is the only right way. The fact that everybody else does it some other way only means that they are wrong"

  7. #7
    Registered User Codeplug's Avatar
    Join Date
    Mar 2003
    Posts
    4,981
    >> ... compiled using the gcc via Cygwin
    Compile with "g++" for C++ code.
    Compile with "gcc" for C code.

    You'll need to post your code and exactly how you're compiling it for additional help.

    gg

  8. #8
    Registered User
    Join Date
    Feb 2012
    Posts
    25
    Quote Originally Posted by iMalc View Post
    Just remove the extern "C". This is already C code, so you shouldn't be telling the C compiler that it's C code.
    Thanks for your suggestion, iMalc; if I remove "extern "C"", now my compiler errors are the following:

    line 33: error: expected declaration specifiers or '...' before '*' token

    line 33: error: 'bool' declared as function returning a function

    line 33: warning: 'dll' attribute directive ignored

    All 3 error messages above refer to the line:

    Code:
    __declspec(dll) bool (*fcn1WrapperPointer)(int numInputs, int Outputs, char *fileName);
    So far, any such simple manipulations/alterations of my functional c-mex s-function code (e.g. removing the 'extern C', removing the __declspec(dll), etc.) haven't yielded a successful solution. It would seem that, in order to link the function declaration to the .dll from which it originates, I'll need some mention of the "HINSTANCE dll" variable that I declare...

  9. #9
    Registered User
    Join Date
    Feb 2012
    Posts
    25
    Quote Originally Posted by Codeplug View Post
    >> ... compiled using the gcc via Cygwin
    Compile with "g++" for C++ code.
    Compile with "gcc" for C code.
    Thanks for the elucidation, Codeplug. To clarify, I am using *gcc* to compile my *C* code. The functions that I want to access within my C code, are coded in C++, and saved in the .dll that I'm currently trying to access.

    You'll need to post your code and exactly how you're compiling it for additional help.
    ok, here goes:

    Code:
    /* in global workspace */
    
    HINSTANCE dll; 
    extern "C" __declspec(dll) bool (*fcn1WrapperPointer)(int numInputs, int numOutputs, char *fileName);  /* line 38 */
    fcn1WrapperPointer fcn1Wrapper;     /* Pointer to "fcn1Wrapper" function within the .dll */            /* line 39 */ 
    
    main(){
    
    dll = LoadLibrary("myLibrary.dll");
    
    if (dll != NULL)
    fcn1Wrapper = (fcn1WrapperPointer)GetProcAddress(dll, "fcn1Wrapper"); 
    
    
    fcn1(6, 6, "Setup_File.txt");   /* line 77 */
    
    }
    Here are the compiler errors I receive from attempting to compile the code above:

    38: error: expected identifier or '(' before string constant
    39: error: expected '=', ',' ,';' , 'asm' or '__attribute__' before 'fcn1Wrapper'
    77: error: 'fcn1Wrapper' undeclared (first use in this function)
    77: error: 'fcn1WrapperPointer' undeclared (first use in this function)
    77: error: expected ';' before 'GetProcAddress'

    I compile using a Makefile, which has the following contents:

    Code:
    # Makefile 
    
    # First, specify the compiler - 
    CC=gcc
    
    # Now, some flags
    CFLAGS=-O3 -ffast-math -fregmove -frerun-loop-opt -fpretend-float
    # the following flags would allow gprof to be used to profile the code
    CFLAGS=-g
    
    # Specify Suffixes
    .SUFFIXES:    .o .c
    
    PROJ=my_Ccode.o  
    
    my_Ccode:    $(PROJ)
                 $(CC) -o $@ $(PROJ) -lm
    
    clean:;        @echo "Cleaning out object files..."
                 rm -f *.o        
    
    # Form the object files from their native C code
    .c.o:;        $(CC) $(CFLAGS) -c $*.c
    I've tried moving things around (e.g. moving the 3 lines from the global workspace to the beginning of main(); calling LoadLibrary() within the global workspace, etc. etc.); however, none of these changes improves the compiler errors.

    Thanks in advance if you can spot what's wrong with my code and/or compilation procedure.

  10. #10
    Registered User
    Join Date
    Jun 2005
    Posts
    6,815
    bool is also a C++ keyword, not a C keyword. In more recent versions of C (1999 standard or later) bool is a macro in one of the standard headers, but the expansion is often not equivalent to C++'s bool (assuming same vendor for both C and C++ compiler).

    If you can't change the DLL (eg to make the return type of the function int, rather than bool), then you need to live with compiling and calling the dll function from C++ (assuming you use the same compiler to build both).

    Additionally, it also doesn't help that, in these two lines
    Code:
        extern "C" __declspec(dll) bool (*fcn1WrapperPointer)(int numInputs, int numOutputs, char *fileName);  /* line 38 */
        fcn1WrapperPointer fcn1Wrapper;     /* Pointer to "fcn1Wrapper" function within the .dll */            /* line 39 */
    the first line is a function declaration (of fcn1WrapperPointer) and the second uses fcn1WrapperPointer as a typename. You probably need to add the keyword "typedef" at the start of the first line.
    Right 98% of the time, and don't care about the other 3%.

    If I seem grumpy or unhelpful in reply to you, or tell you you need to demonstrate more effort before you can expect help, it is likely you deserve it. Suck it up, Buttercup, and read this, this, and this before posting again.

  11. #11
    Registered User Codeplug's Avatar
    Join Date
    Mar 2003
    Posts
    4,981
    In your original sample in post #1, replace "mdlStart" with "main". And you should be able to replace the "bool" with "char" - I believe a char in C is the binary equivalent to bool in C++.

    All the extern/__declspec stuff is for compile-time linking to DLL's (client side), or exporting DLL symbols without a .DEF file (dll side). What you are doing is run-time linking via LoadLibrary - so all you need is the proper function pointer signature (fcn1WrapperPointer typedef) to use with GetProcAddress.

    gg

  12. #12
    Registered User
    Join Date
    Feb 2012
    Posts
    25
    bool is also a C++ keyword, not a C keyword. In more recent versions of C (1999 standard or later) bool is a macro in one of the standard headers, but the expansion is often not equivalent to C++'s bool (assuming same vendor for both C and C++ compiler).
    Thanks for the clarification, grumpy; I was aware that bool isn't a C type, but wasn't sure how to go about correcting for this. I'll have to look at the C++ code more closely to determine how feasible it will be to eliminate all of the bools.

  13. #13
    Registered User
    Join Date
    Feb 2012
    Posts
    25
    Quote Originally Posted by Codeplug View Post
    In your original sample in post #1, replace "mdlStart" with "main". And you should be able to replace the "bool" with "char" - I believe a char in C is the binary equivalent to bool in C++.

    All the extern/__declspec stuff is for compile-time linking to DLL's (client side), or exporting DLL symbols without a .DEF file (dll side). What you are doing is run-time linking via LoadLibrary - so all you need is the proper function pointer signature (fcn1WrapperPointer typedef) to use with GetProcAddress.
    Thanks for your advice, Codeplug; reverting to the original c-mex s-function code but just changing 'bool' to 'char', worked! The code now compiles and runs!

    Update: Fyi, I found that if I include the <stdbool.h> header, I can revert to using 'bool' in my global declaration and elsewhere in my code. Thanks again for the suggestion, grumpy.
    Last edited by CodeRed; 11-21-2012 at 11:25 AM.

  14. #14
    Registered User Codeplug's Avatar
    Join Date
    Mar 2003
    Posts
    4,981
    >> I can revert to using 'bool' in my global declaration and elsewhere in my code.
    You should use "char" in your fcn1WrapperPointer typedef. What's in <stdbool.h> may not be binary compatible with the C++ bool that was compiled in the the DLL - but "char" should be compatible since they are both 1 byte in size.

    <stdbool.h> may use an int or an enum - making it 4 bytes in size.

    gg

  15. #15
    Registered User
    Join Date
    Feb 2012
    Posts
    25
    Quote Originally Posted by Codeplug View Post
    >> I can revert to using 'bool' in my global declaration and elsewhere in my code.
    You should use "char" in your fcn1WrapperPointer typedef. What's in <stdbool.h> may not be binary compatible with the C++ bool that was compiled in the the DLL - but "char" should be compatible since they are both 1 byte in size.

    <stdbool.h> may use an int or an enum - making it 4 bytes in size.

    gg
    Ok, thanks for that clarification.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Accessing Structs in Functions Problem
    By opeth in forum C Programming
    Replies: 8
    Last Post: 04-02-2012, 09:11 PM
  2. Accessing member functions of sockaddr_in
    By Stack Overflow in forum Linux Programming
    Replies: 8
    Last Post: 01-29-2005, 11:26 AM
  3. Accessing main form from functions in other classes
    By pj_martins in forum C++ Programming
    Replies: 1
    Last Post: 11-05-2004, 09:27 AM
  4. Replies: 2
    Last Post: 11-28-2003, 09:23 AM
  5. Accessing CEdit Member Functions Inside CEditView ::MFC
    By kuphryn in forum Windows Programming
    Replies: 0
    Last Post: 04-10-2002, 08:52 PM