Error: C3861: 'spis_CreateInstance': identifier not found



  • I'm trying to call functions from a DLL and can't make it work. If I use the same code in a C++ console it works fine.
    I'm using the notepad example program as a template to get started so ignore the file stuff.Then I added my working C++ code to the button. I get this error C:\Qt\Qt5.1.0\Tools\QtCreator\bin\Not\notepad.cpp:26: error: C3861: 'spis_CreateInstance': identifier not found

    Here's some of the code.

    @#include "notepad.h"
    #include "ui_notepad.h"
    #include <QFileDialog>
    #include <QFile>
    #include <QMessageBox>
    #include <QTextStream>

    extern "C" {
    #include "SpiStorm.h"
    }
    Notepad::Notepad(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::Notepad)
    {
    ui->setupUi(this);
    }

    Notepad::~Notepad()
    {
    delete ui;
    }

    void Notepad::on_quithButton_clicked()
    {
    int Res = 0;
    Res = spis_CreateInstance();
    Res = spis_Connect("050112020E7", 3300);

    //qApp->quit();
    

    }

    void Notepad::on_actionSave_triggered()
    {
    QString fileName = QFileDialog::getSaveFileName(this, tr("Save File"), QString(),
    tr("Text Files (.txt);;C++ Files (.cpp *.h)"));

               if (!fileName.isEmpty()) {
                   QFile file&#40;fileName&#41;;
                   if (!file.open(QIODevice::WriteOnly)) {
                       // error message
                   } else {
                       QTextStream stream(&file);
                       stream << ui->textEdit->toPlainText();
                       stream.flush();
                       file.close();
                   }
               }
    

    }

    void Notepad::on_actionOpen_triggered()
    {
    QString fileName = QFileDialog::getOpenFileName(this, tr("Open File"), QString(),
    tr("Text Files (.txt);;C++ Files (.cpp *.h)"));

           if (!fileName.isEmpty()) {
               QFile file&#40;fileName&#41;;
               if (!file.open(QIODevice::ReadOnly)) {
                   QMessageBox::critical(this, tr("Error"), tr("Could not open file"));
                   return;
               }
               QTextStream in(&file);
               ui->textEdit->setText(in.readAll());
               file.close();
           }
    

    }@


  • Lifetime Qt Champion

    Hi and welcome to devnet,

    Do you link properly to that lib ?



  • Thanks for the welcome and prompt reply!

    bq. Do you link properly to that lib ?

    I think so. Like I said, the source code works in a C++ console program.
    I'm not sure about linking, I just added all the lib, DLL and header files. I don't know what I'm supposed to do to link them other than adding
    @extern "C" {
    #include "SpiStorm.h"
    }@


  • Lifetime Qt Champion

    Did you add

    @LIBS += -lnameofyourlib@

    to your pro file ?

    If you are using QtCreator you can make it do the job for you



  • N where should I put it?
    @#-------------------------------------------------

    Project created by QtCreator 2013-08-09T10:31:41

    #-------------------------------------------------

    QT += core gui

    greaterThan(QT_MAJOR_VERSION, 4): QT += widgets

    TARGET = Not
    TEMPLATE = app

    SOURCES += main.cpp
    notepad.cpp
    ../../../../../../Users/fc8r7c/Desktop/DLL_Demo_ONSemi/DLL_Demo_ONSemi/DLL_Demo/DLL_Demo.cpp
    SpiStorm.cpp

    HEADERS += notepad.h
    ../../../../../../Users/fc8r7c/Desktop/DLL_Demo_ONSemi/DLL_Demo_ONSemi/inc/SpiStorm.h
    ../../../../../../Users/fc8r7c/Desktop/DLL_Demo_ONSemi/DLL_Demo_ONSemi/DLL_Demo/stdafx.h
    SpiStorm.h

    FORMS += notepad.ui

    OTHER_FILES +=
    ../../../../../../Users/fc8r7c/Desktop/DLL_Demo_ONSemi/DLL_Demo_ONSemi/lib/SpiStorm.lib
    ../../../../../../Users/fc8r7c/Desktop/DLL_Demo_ONSemi/DLL_Demo_ONSemi/DLL_Demo/SpiStorm.dll
    @



  • I cleaned it up a little and here's what I have now.
    @#-------------------------------------------------

    Project created by QtCreator 2013-08-09T10:31:41

    #-------------------------------------------------

    QT += core gui
    LIBS += SpiStorm
    greaterThan(QT_MAJOR_VERSION, 4): QT += widgets

    TARGET = Not
    TEMPLATE = app

    SOURCES += main.cpp
    notepad.cpp

    HEADERS += notepad.h
    SpiStorm.h

    FORMS += notepad.ui

    OTHER_FILES +=
    SpiStorm.dll
    SpiStorm.lib
    @

    Here's the header file
    @#ifndef SPI_STORM_C
    #define SPI_STORM_C

    #define EX __declspec(dllexport)

    extern "C"
    {
    EX int spis_CreateInstance(void);
    EX void spis_DeleteInstance(int Handle);
    EX void spis_SelectInstance(int Handle);

    EX int spis_ScanDev(unsigned char *pType, unsigned int *pID, unsigned char *pSerNum);
    EX int spis_Connect(char *pSerNum, unsigned short SupplyVoltage);
    EX int spis_Disconnect(void);
    EX int spis_SetDisconnectCallback(void *pObj, void *pFct);

    EX int spis_LoadPrjFile(char *pFileName, bool CheckSyntax, bool SetInitial);

    EX int spis_ExecProg(bool Blocking);
    EX int spis_ExecProgBuf(char **pBufOut, char **pBufIn, unsigned int NrBuf, bool Blocking);

    EX int spis_ExecMacro(char *pLabel,char *pBufOut, char *pBufIn);

    EX int spis_StartSequence(void);
    EX int spis_EndOfSequence(void);

    EX int spis_ExternalPowerSelected(bool *pSelected);
    EX int spis_ExternalClockPresent(bool *pPresent);

    EX int spis_Abort(void);

    EX int spis_GetState(void);
    EX int spis_SetStateCallback(void *pObj, void *pFct);

    EX int spis_SetSysErrCallback(void *pObj, void *pFct);
    };

    #endif SPI_STORM_C@



  • I added stdafx.cpp and stdafx.h and now I get a different error.
    notepad.obj:-1: error: LNK2019: unresolved external symbol spis_CreateInstance referenced in function "private: void __cdecl Notepad::on_quithButton_clicked(void)" (?on_quithButton_clicked@Notepad@@AEAAXXZ)


  • Lifetime Qt Champion

    stdafx ? From a Qt app ? You should not have them at all.
    Anyway, you have your external lib in the same folder as the sources so your pro file should rather contain something like this:

    @
    QT += core gui

    greaterThan(QT_MAJOR_VERSION, 4): QT += widgets

    TARGET = Not
    TEMPLATE = app

    SOURCES += main.cpp
    notepad.cpp

    HEADERS += notepad.h

    FORMS += notepad.ui

    INCLUDEPATH += .
    LIBS += -L$$PWD
    -lSpiStorm
    @

    Hope it helps




  • Lifetime Qt Champion

    Strange...
    Can you try to add this ?

    @QMAKE_LFLAGS += /OPT:NOREF@

    I don't have a Window computer handy right now so I can't test the lib



  • Thanks, I'll try that on Monday.



  • That didn't help. This is frustrating. I feel like I'm right on the edge of getting this to work but I don't know how to tell this program where the library is or something as simple as that. Any more ideas? Have you looked at the file tree and is it setup right?


  • Lifetime Qt Champion

    Just to be sure, are you building your Qt application in 32 or 64 bit ? SpiStorm seems to be 32

    Also no need for the NOREF line



  • I didn't think of that. I'll check my settings.
    Thanks



  • So how do I change it?
    While I'm waiting, I'm downloading the 32Bit version of Qt and I hope to be able to run in either version without uninstalling the 64Bit version.


  • Lifetime Qt Champion

    Simple:

    Add the Qt you just installed to the Qt version

    Make a kit with it

    Change the kit for your project

    Build and run !



  • I have a new related problem. I get past all the code up to adding my data. I get junk in the pDataOut.
    This should be an easy one right. Fingers crossed.

    @if (Res == 0) {
    char *pDataOut = (char *)malloc(6);
    char *pDataIn = (char *)malloc(6);

               for (int i=0; i<4; i++) {
                        *(pDataOut+i) = ((i%2)==0) ? 0xAA : 0x00;
                        *(pDataIn+i) = 0;
                     }
    
               if (Res == 0) {
                  printf("Adding macro Data32...");
                  Res = spis_ExecMacro("Data32", pDataOut+1, pDataIn+1);
                  if (Res != 0) { printf("Macro Data32 failed!\n"); }
                  else { printf("done\n"); }
               }
    
               delete pDataOut;
               delete pDataIn;
            }@
    

    Here's the debug info
    Locals
    Res -2142240767 int
    SpiHandle -2147155967 int
    i 4 int
    pDataIn @0x265d760 "" char *
    *pDataIn 0 '\0' char
    pDataOut "ª\000ª" @0x3cbfd4 char *
    *pDataOut -86 / 170 char
    pPojectFileName "C:\Spi_StormProjects\24_BIT_Command.ssp" @0x3cbfcc char *
    *pPojectFileName 67 'C' char
    this @0x3cf7b8 Notepad *
    QMainWindow class QMainWindow QMainWindow
    QWidget class QWidget QWidget
    staticMetaObject <Value unavailable error>
    staticMetaObject struct QMetaObject QMetaObject
    ui @0x869350 Ui::Notepad *
    Inspector
    Expressions
    Return Value
    Tooltip


  • Lifetime Qt Champion

    Why do you put data in pDataOut ? Shouldn't be in pDataIn ?



  • This is part of an example console program that worked as such. Maybe I should run that program in debug mode and see what it's sending. I'm sending data out of my PC to a SPI module which transfers these bits at 50MHz to a custom test fixture.


  • Lifetime Qt Champion

    So pDataOut is what goes to the SPI module and pDataIn is what the module sends ?

    Also, why the +1 ?



  • So pDataOut is what goes to the SPI module and pDataIn is what the module sends ? Yes, pDataIn reads back from the module.

    Also, why the +1 ? I have no idea.



  • My intent is to send a 4 byte command.


  • Lifetime Qt Champion

    It's getting strange, the 4byte command is stored in a 6byte array, the command start at 0 but you send starting at byte 1.

    Sounds dubious...



  • Well I did clip a lot of the original code and just use what I thought I would need. I ran the console program without the +1s and changed the mallocs 2to 4. This seems to work great in the console program but again, not in the Qt5. Grrr.
    @ if (Res == 0) {
    char *pDataOut = (char *)malloc(4);
    char *pDataIn = (char *)malloc(4);

                   for (int i=0; i<4; i++) {
                      *(pDataOut+i) = ((i%2)==0) ? 0xFA : 0x02;
                      *(pDataIn+i) = 0;
                     }
    
    
                   if (Res == 0) {
                            printf("Adding macro Data32...");
                            Res = spis_ExecMacro("Data32", pDataOut, pDataIn);
                            if (Res != 0) { printf("failed!\n"); }
                            else { printf("done\n"); }
    

    @


  • Lifetime Qt Champion

    If you are clipping too much code, you might be missing some initialization step or something



  • I don't have any errors but I can't get past this if statement so I'm not connecting through the DLL for some reason. Where is the disconnect from the button to the DLL? The code is the same and it should work. I've even added the conio and stdio include files. This is really strange.

    @ int Res = 0;
    int SpiHandle = spis_CreateInstance();
    Res = spis_Connect("050112020E7", 3300);

    if (Res == 0) {@


  • Lifetime Qt Champion

    Since you have that example that works fine, did you try to simply get the "whole" code from it and put it in a function that you would call in your program ?

    Then you can try to clean it and remove what you don't need



  • I added the code to the main.cpp. Still doesn't open the console view. Seems like Qt5 doesn't want to open console programs.

    @#include "notepad.h"
    #include <QApplication>
    #include <conio.h>
    #include <malloc.h>
    #include <direct.h>
    #include <stdio.h>
    extern "C" {
    #include "SpiStorm.h"
    }
    int main(int argc, char *argv[])
    {
    QApplication a(argc, argv);
    Notepad w;
    w.show();
    int Res = 0;

    //
    // Welcome message
    //
    printf("\nStarting DLL demo...\n\n");
    
    //
    // Open the SPI Storm library and retrieve handle
    //
    printf("Opening the SPI Storm library and retrieve handle...");
    int SpiHandle = spis_CreateInstance();
    printf("done\n\n");
    
    //
    // Connect to a SPI Storm device
    //
    //char SerNum[256];
     Res = spis_Connect("050112020E7", 3300);
    if (Res != 0) { printf("Serial Number failed!\n"); }
    else { printf("done\n"); }
    
    
    ///////////////////////////
    // Load SPI project file //
    ///////////////////////////
    if (Res == 0) {
       char *pPojectFileName = "C:\\Spi_StormProjects\\24_BIT_Command.ssp";
       printf("\nLoading SPI configuration file \"%s\"...", pPojectFileName);
       Res = spis_LoadPrjFile&#40;pPojectFileName, false, true&#41;;
       if (Res != 0) { printf("failed!\n"); }
       else { printf("done\n"); }
    }
    
    //
    // Burst the macros
    //
    if (Res == 0) {
       char *pDataOut = (char *)malloc(4);
       char *pDataIn  = (char *)malloc(4);
    
       for (int i=0; i<4; i++) {
          *(pDataOut+i) = ((i%2)==0) ? 0x00 : 0x02;
          *(pDataIn+i) = 0;
       }
    
      /* printf("Initialise the burst sequence...");
       Res = spis_StartSequence();
       if (Res != 0) { printf("failed!\n"); }
       else { printf("done\n"); }*/
    
       if (Res == 0) {
          printf("Adding macro Data32...");
          Res = spis_ExecMacro("Data32", pDataOut, pDataIn);
          if (Res != 0) { printf("failed!\n"); }
          else { printf("done\n"); }
       }
    
      /* if (Res == 0) {
          printf("Adding macro B5P0...");
          Res = spis_ExecMacro("B5P0", pDataOut+1, pDataIn+1);
          if (Res != 0) { printf("failed!\n"); }
          else { printf("done\n"); }
       }
    
       if (Res == 0) {
          printf("Adding macro B6P0...");
          Res = spis_ExecMacro("B6P0", pDataOut+2, pDataIn+2);
          if (Res != 0) { printf("failed!\n"); }
          else { printf("done\n"); }
       }
    
       if (Res == 0) {
          printf("Adding macro B1P0...");
          Res = spis_ExecMacro("B1P0", pDataOut+3, pDataIn+3);
          if (Res != 0) { printf("failed!\n"); }
          else { printf("done\n"); }
       }
    
       if (Res == 0) {
          printf("Adding macro B2P0...");
          Res = spis_ExecMacro("B2P0", pDataOut+4, pDataIn+4);
          if (Res != 0) { printf("failed!\n"); }
          else { printf("done\n"); }
       }
    
       if (Res == 0) {
          printf("Adding macro B3P0...");
          Res = spis_ExecMacro("B3P0", pDataOut+5, pDataIn+5);
          if (Res != 0) { printf("failed!\n"); }
          else { printf("done\n"); }
       }
    
       printf("Execute the burst sequence...");
       Res = spis_EndOfSequence();
       if (Res != 0) { printf("failed!\n"); }
       else { printf("done\n"); }*/
    
       delete pDataOut;
       delete pDataIn;
    }
    
    //
    // Close the SPI Storm library
    //
    printf("\nClosing the SPI Storm library...");
    spis_DeleteInstance(SpiHandle);
    printf("done\n");
    
    //
    // Wait for user input to close the window
    //
    printf("\nPress any key...\n");
    //int ch = _getch();
    
    
    return a.exec&#40;&#41;;
    

    }
    @



  • I get this output when I run it. The serial number is fine, it must be getting scrambled somehow.
    Starting DLL demo...

    Opening the SPI Storm library and retrieve handle...done

    Serial Number failed!

    Closing the SPI Storm library...done

    Press any key...

    The program has unexpectedly finished.
    C:\Qt\Qt5.1.0\Tools\QtCreator\bin\build-Not-Desktop_Qt_5_1_0_MSVC2012_32bit-Debug\debug\Not.exe exited with code -2147155967


  • Lifetime Qt Champion

    Gui applications don't open a command line (unless you add CONFIG += console), but you should have the output shown in the "Application output" panel in QtCreator

    @/* printf("Initialise the burst sequence...");
    Res = spis_StartSequence();
    if (Res != 0) { printf("failed!\n"); }
    else { printf("done\n"); }*/

      /*printf("Execute the burst sequence...");
       Res = spis_EndOfSequence();
       if (Res != 0) { printf("failed!\n"); }
       else { printf("done\n"); }*/
    

    @

    These parts might be the thing you are missing to get your data right. They seem to initialize something for the following calls and then put things back to normal.


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.