Extended Stored Procedures from C++ Require extern "C"

ID: Q205415


The information in this article applies to:


SUMMARY

In order to compile C+/+ projects into a SQL Server extended procedure it is required to make the header file Srv.h externally declared as it was intended for ANSII "C" applications. Not doing this will result in the error "LNK2001" during compile time.


MORE INFORMATION

Mark the include file Srv.h as external. This is done with the C++ declarator "extern" and specifying the language as being "C". In the previous sample remove the comments on the lines:


//extern "C"{
#include <srv.h>
//} 
To read:

extern "C"{
#include <srv.h>
} 
The project should now compile with out any errors. To run the extended stored procedure, follow these steps:
  1. Build the Dynamic Link Library by pressing F7 or F5. F5 prompts you for an executable name, this is for debugging purposes and is not needed for this simple DLL so press CANCEL.


  2. To set where the dynamic link library is built to, choose Settings from the Property menu. On the Link tab there is text box labeled Output file name. The default is \debug. For the example here, the whole path to the DLL might be (this will vary):
    
    "c:\simpXP\debug\simpXP.dll" 
    NOTE: The whole path and name must conform to the 8.3 naming conventions for SQL Server.


  3. Start ISQL/w and run the following script:
    
    --**********************************************
    sp_dropextendedproc  xp_Easy
    GO
    sp_addextendedproc  xp_Easy, "c:\simpXP\debug\simpXP.dll"
    GO
    Execute xp_Easy
    --********************************************** 
    The output should look like:
    
    "This is how easy XP's can be!" 


To reproduce the error, follow these steps from Visual C++ 5.0 or 6.0:
  1. From the File menu choose New (CTRL+N).


  2. From the Projects tab select Win32 Dynamic-Link Library.


  3. Type in a project name such as "simpXP" and press OK.


  4. Press (CTRL+N), this takes you back to New but should default to Files.


  5. From the Files tab select C++ source file.


  6. Give the source file a name (such as simpXP.cpp) and press OK.


  7. Paste in the following code to the source file:
    
    //************************************************
    #define      DBNTWIN32
    #include    <windows.h>
    #include    <sqlfront.h>
    #include    <sqldb.h>
    //extern "C"{
    #include    <srv.h>
    //}
    #define  XP_NOERROR      0
    #define  SRV_MAXERROR           20000
    #define  CMDSHELL_ERROR         SRV_MAXERROR + 2
    int xp_Easy(SRV_PROC * srvproc)
    {
    srv_sendmsg(srvproc, SRV_MSG_INFO , CMDSHELL_ERROR, SRV_INFO, (DBTINYINT)0,
           NULL, 0, 0,  "This is how easy XP's can be!", SRV_NULLTERM);
    srv_senddone(srvproc, SRV_DONE_MORE, 0, 0);
    return(XP_NOERROR);
    }//end
    //************************************************ 


  8. Press CTRL+N.


  9. From the Files tab select text file. This will be the Definition file.


  10. Give the Definition file a name (such as simpXP.def) and click OK.


  11. Paste in the following code to this file:
    
     LIBRARY   xp_Easy
     DESCRIPTION 'SQL Server Extended Stored Procedure - DLL'
     EXPORTS
              xp_Easy 


  12. From the Project menu select Settings.


  13. On the Link tab go to the text box labeled Object/library modules: and add the libraries opends60.lib and ntwdblib.lib. NOTE: To avoid problems please add these to the end of the libraries currently in the list.


  14. Press F7. Visual C++ prompts you to see if you would like build the DLL. Choose YES.


  15. In attempting to compile you will now get the following three errors:
    simpXP.obj : error LNK2001: unresolved external symbol "int __cdecl srv_senddone(struct srv_proc *,unsigned short,unsigned short,long)" (?srv_senddone@@YAHPAUsrv_proc@@GGJ@Z)
    simpXP.obj : error LNK2001: unresolved external symbol "int __cdecl srv_sendmsg(struct srv_proc *,int,long,unsigned char,unsigned char,char *,int,unsigned short,char *,int)" (?srv_sendmsg@@YAHPAUsrv_proc@@HJEEPADHG1H@Z)
    c:\simpXP3.dll : fatal error LNK1120: 2 unresolved externals
    NOTE: If you get more (or different) errors it is likely Visual C++ does not know where the SQL Include or Library files are located. The easiest solution is to move the files to the \VC\INCLUDE directory from the PTK\ODS\INCLUDE directory and the file Ntwdblib.lib from \PTK\DBLIB\LIB to the \VC\LIB and the file Opends60.lib from \PTK\ODS\LIB to \VC\LIB.

    Even after installing the SQL Programmers Tool Kit (PTK) (found in SQL 6.5 Workstation), you may also find that you are missing the sqlfront.h and sqldb.h header files. Make sure that you have copies of these files in the VC\include directory if the compiler cannot locate them.

    Regarding all of the above, the same thing can be accomplished by fully qualifying the path but the syntax is different for the #inlcude so please consult your C++ documentation for more information.



REFERENCES

For more indepth examples of extended stored procedures please refer to the Programmer's Toolkit samples:

This limitation is also documented in the following Microsoft Knowledge Base articles:

NOTE: They do not mention that this requirement also holds true for SQL extended procedures.
Q96433 INF: Using DB-Library with C++

Q157919 INF: Building an ODS Application with MFC

Q108522 FIX: L2029 Error Calling ODBC Functions from ODBC SDK

Additional query words: hello world simple


Keywords          : SSrvESQL_C SSrvStProc SSrvTran_SQL kbSQLServ650 kbSQLServ700 
Version           : winnt:6.5,7.0
Platform          : winnt 
Issue type        : kbhowto 

Last Reviewed: June 2, 1999