error occurred when using mex to build binary MEX-file

1 Ansicht (letzte 30 Tage)
Kit Mai
Kit Mai am 21 Nov. 2011
Kommentiert: James Tursa am 5 Feb. 2015
Hi, I am write a mexFunction to call C in MATLAB. Compiler:Dev-c++, OS:windowXP
My C functions are all in the "spinapi.c" file, and it has a header "spinapi.h", they work perfectly fine.
The following dds2_sine.c file is the file contains the gateway routine I wrote, it just calls the dds2_sine function in this same file.
#include <stdlib.h>
#include <stdio.h>
#include "spinapi.h"
#include "mex.h"
#define CLOCK_FREQ 75.0 // This value must be 75 MHz for standard PBDDS-II-300 boards
// User friendly names for the control bits
#define TX_ENABLE 1
#define TX_DISABLE 0
#define PHASE_RESET 1
#define NO_PHASE_RESET 0
#define DO_TRIGGER 1
#define NO_TRIGGER 0
#define FREQ0 0
#define FREQ1 1
#define AMP0 0
#define PHASE0 0
#define PHASE1 1
#define PHASE2 2
#define START_LOCATION (0x40000+0x07)
#define FLAG_STATES (0x40000+0x08)
int detect_boards();
int select_board(int numBoards);
void
dds2_sine(double time1, double time2)
{
int start, i, isr1;
int numBoards;
//Uncommenting the line below will generate a debug log in your current directory
//that can help debug any problems that you may be experiencing
//pb_set_debug(1);
printf ("Copyright (c) 2010 SpinCore Technologies, Inc.\n\n");
printf("Using SpinAPI library version %s\n", pb_get_version());
if((numBoards = detect_boards()) > 1) { /*If there is more than one board in the system, have the user specify.*/
select_board(numBoards); /*Request the board numbet to use from the user*/
}
if (pb_init () != 0) {
printf ("Error initializing board: %s\n", pb_get_error ());
system("pause");
}
printf("This example program tests the analog and TTL outputs of the PBDDS-II.\n\n This program will produce a 10.0 MHz signal on both channels that is on for 10 microseconds, off for 200 microseconds, and then repeats this pattern.\n\n");
printf("The RF pulses on Channels 1 and 2 are offset by 90 degrees.\n\n");
printf("A TTL logical high signal on the IRQ0 pin will cause an ISR to be performed \nthat pronduces a 2.0 MHz signal on both channels that is on for 200.0 us, off \nfor 200.0 us and repeats this pattern 10,000 times. It will turn both channels \noff for 100.0 us and then returns to the main pulse program.\n\n");
printf("NOTE: It is important to terminate all signals properly (i.e. with a 50 Ohm\nterminating resistor at the end of your cable). A reconstructing filter must\nalso be used at the RF outputs. When viewing the RF signals on an oscilloscope,the oscilloscope should be triggered using a TTL signal\n\n");
printf("See manual for details at: http://www.spincore.com/\n\n");
system("pause");
printf("\n\n");
pb_core_clock(CLOCK_FREQ); //Set the PB core clock value.
/****** THIS SECTION PROGRAMS REGISTERS FOR CHANNEL 1 (DDS0) ******/
pb_select_dds(0); //Select DDS0 (this is selected by default.)
pb_start_programming(FREQ_REGS); //Program DDS0's frequency registers. NOTE: Each Channel has 16 available Frequency registers
pb_set_freq(10.0*MHz); //Program Frequency Register 0.
pb_set_freq(4.0*MHz); //Program Frequency Register 1.
pb_stop_programming();
pb_start_programming(TX_PHASE_REGS); //Program DDS0's phase registers. NOTE: Each Channel has 8 available Phase registers
pb_set_phase(270.0); //Program Phase Register 0.
pb_set_phase(70.0); //Program Phase Register 1.
// PHASE1 offset is introduced to improve the initial RF pulse response. This phase is used during the "off" time of the RF pulse.
pb_stop_programming();
pb_set_amp(1.0,0); //Program DDS0's amplitude registers.
// NOTE: Each Channel has 4 available amplitude registers
/**********************************************************************/
/***** THIS SECTION PROGRAMS REGISTERS FOR CHANNEL 2 (DDS1) *****/
pb_select_dds(1); //Select DDS1.
pb_start_programming(FREQ_REGS); //Program DDS1's frequency registers.
pb_set_freq(10.0*MHz); //Program Frequency Register 0.
pb_set_freq(2.0*MHz); //Program Frequency Register 1.
pb_stop_programming();
pb_start_programming(TX_PHASE_REGS); //Program DDS1's phase registers.
pb_set_phase(0.0); //Program Phase Register 0.
pb_set_phase(70.0); //Program Phase Register 1.
pb_stop_programming();
pb_set_amp(1.0,0); //Program DDS1's amplitude registers.
/************************************************************************/
pb_start_programming(PULSE_PROGRAM); //This line is used to start programming the pulse program.
start = pb_inst_dds2(FREQ0, PHASE0, AMP0, TX_ENABLE, NO_PHASE_RESET, FREQ0, PHASE0, AMP0, TX_ENABLE, NO_PHASE_RESET, 0xfff, CONTINUE, 0, time1*us);
pb_inst_dds2(FREQ0, PHASE1, AMP0, TX_DISABLE, PHASE_RESET, FREQ0, PHASE1, AMP0, TX_DISABLE, PHASE_RESET, 0x000, BRANCH, start, time2*us);
/*********************************************************************************************************
* The section below specifies the interrupt sub routine *
* The instructions follow the same general structure except that LOOP, END_LOOP and RTI instructions *
* are used. Here you will notice that where Channel 1 uses Frequency register 1, but Channel 2 *
* uses Frequency register 0, so they are not the same frequency *
*********************************************************************************************************/
isr1 = pb_inst_dds2(FREQ1, PHASE0, AMP0, TX_ENABLE, NO_PHASE_RESET, FREQ1, PHASE0, AMP0, TX_ENABLE, NO_PHASE_RESET, 0xfff, LOOP, 10000, 200.0*us);
pb_inst_dds2(FREQ1, PHASE0, AMP0, TX_DISABLE, PHASE_RESET, FREQ0, PHASE0, AMP0, TX_DISABLE, PHASE_RESET, 0x000, END_LOOP, isr1, 200.0*us);
pb_inst_dds2(FREQ0, PHASE0, AMP0, TX_DISABLE, PHASE_RESET, FREQ0, PHASE0, AMP0, TX_DISABLE, PHASE_RESET, 0x000, RTI, isr1, 100.0*us);
pb_stop_programming(); // This line ends the pulse program
pb_write_register (START_LOCATION, 0);
pb_write_register (FLAG_STATES, 0);
/*** The section below sets the interrupt masks ***/
pb_set_isr(0, isr1); //Program IRQ0 ISR
pb_set_irq_enable_mask(0x1); //Interrupt enable mask. 0x1 enables IRQ0.
pb_set_irq_immediate_mask(0x0); //Set which IRQs are immediate IRQs (immediately perform ISR)
// Send a software trigger (i.e. pb_start()) to the board to begin execution of the program
pb_start();
printf("Continuing will stop program exectution\n");
system("pause");
pb_stop();
pb_close();
}
/* The gateway function */
void mexFunction( int nlhs, mxArray *plhs[],
int nrhs, const mxArray *prhs[])
{
double t1;
double t2;
/* check for proper number of arguments */
if(nrhs!=2) {
mexErrMsgIdAndTxt("MyToolbox:dds2_sine:nrhs","Two inputs required.");
}
/* make sure the first input argument is scalar */
if( !mxIsDouble(prhs[0]) ||
mxIsComplex(prhs[0]) ||
mxGetNumberOfElements(prhs[0])!=1 ) {
mexErrMsgIdAndTxt("MyToolbox:dds2_sine:notScalar","Input1 must be a scalar.");
}
if( !mxIsDouble(prhs[1]) ||
mxIsComplex(prhs[1]) ||
mxGetNumberOfElements(prhs[1])!=1 ) {
mexErrMsgIdAndTxt("MyToolbox:dds2_sine:notScalar","Input2 must be a scalar.");
}
/* get the value of the scalar input */
t1 = mxGetScalar(prhs[0]);
t2 = mxGetScalar(prhs[1]);
/* call the computational routine */
dds2_sine(t1,t2);
}
int
detect_boards()
{
int numBoards;
numBoards = pb_count_boards(); /*Count the number of boards */
if (numBoards <= 0) {
printf("No Boards were detected in your system. Verify that the board is properly powered and connected.\n\n");
system("PAUSE");
exit(-1);
}
return numBoards;
}
int
select_board(int numBoards)
{
int choice;
do {
printf("Found %d boards in your system. Which board should be used? (0-%d): ",numBoards, numBoards - 1);
fflush(stdin);
scanf("%d", &choice);
if (choice < 0 || choice >= numBoards) {
printf("Invalid Board Number (%d).\n", choice);
}
} while (choice < 0 || choice >= numBoards);
pb_select_board(choice);
printf("Board %d selected.\n", choice);
return 0;
}
But when I type mex dds2_sine.c to build the binary MEX-file, I got the following error:
>> mex dds2_sine_testing.c
Writing library for dds2_sine_testing.mexw32
c:\docume~1\weijie\locals~1\temp\mex_jg~1\dds2_sine_testing.obj .text: undefined reference to '_pb_get_version'
c:\docume~1\weijie\locals~1\temp\mex_jg~1\dds2_sine_testing.obj .text: undefined reference to '_pb_init'
c:\docume~1\weijie\locals~1\temp\mex_jg~1\dds2_sine_testing.obj .text: undefined reference to '_pb_get_error'
c:\docume~1\weijie\locals~1\temp\mex_jg~1\dds2_sine_testing.obj .text: undefined reference to '_pb_core_clock'
c:\docume~1\weijie\locals~1\temp\mex_jg~1\dds2_sine_testing.obj .text: undefined reference to '_pb_select_dds'
c:\docume~1\weijie\locals~1\temp\mex_jg~1\dds2_sine_testing.obj .text: undefined reference to '_pb_start_programming'
c:\docume~1\weijie\locals~1\temp\mex_jg~1\dds2_sine_testing.obj .text: undefined reference to '_pb_set_freq'
c:\docume~1\weijie\locals~1\temp\mex_jg~1\dds2_sine_testing.obj .text: undefined reference to '_pb_stop_programming'
c:\docume~1\weijie\locals~1\temp\mex_jg~1\dds2_sine_testing.obj .text: undefined reference to '_pb_set_phase'
c:\docume~1\weijie\locals~1\temp\mex_jg~1\dds2_sine_testing.obj .text: undefined reference to '_pb_set_amp'
c:\docume~1\weijie\locals~1\temp\mex_jg~1\dds2_sine_testing.obj .text: undefined reference to '_pb_inst_dds2'
c:\docume~1\weijie\locals~1\temp\mex_jg~1\dds2_sine_testing.obj .text: undefined reference to '_pb_write_register'
c:\docume~1\weijie\locals~1\temp\mex_jg~1\dds2_sine_testing.obj .text: undefined reference to '_pb_set_isr'
c:\docume~1\weijie\locals~1\temp\mex_jg~1\dds2_sine_testing.obj .text: undefined reference to '_pb_set_irq_enable_mask'
c:\docume~1\weijie\locals~1\temp\mex_jg~1\dds2_sine_testing.obj .text: undefined reference to '_pb_set_irq_immediate_mask'
c:\docume~1\weijie\locals~1\temp\mex_jg~1\dds2_sine_testing.obj .text: undefined reference to '_pb_start'
c:\docume~1\weijie\locals~1\temp\mex_jg~1\dds2_sine_testing.obj .text: undefined reference to '_pb_stop'
c:\docume~1\weijie\locals~1\temp\mex_jg~1\dds2_sine_testing.obj .text: undefined reference to '_pb_close'
c:\docume~1\weijie\locals~1\temp\mex_jg~1\dds2_sine_testing.obj .text: undefined reference to '_pb_count_boards'
c:\docume~1\weijie\locals~1\temp\mex_jg~1\dds2_sine_testing.obj .text: undefined reference to '_pb_select_board'
C:\PROGRA~1\MATLAB\R2009A\BIN\MEX.PL: Error: Link of 'dds2_sine_testing.mexw32' failed.
??? Error using ==> mex at 218
Unable to complete successfully.
What does it mean by "undefined reference" ?
These '_pb_get_version', '_pb_init', '_pb_get_error' are the functions called in my computational routine, they are in the spinapi.c file. And the program does include the spinapi.h!
Why would this error occur? Can someone help me solve this error?
Thank you so much.

Antworten (1)

James Tursa
James Tursa am 21 Nov. 2011
You need to include all of your source code on the mex command line unless it is included in the other files. e.g.,
mex dds2_sine_testing.c spinapi.c
And any other source code that I missed must be on the mex command line as well.
  4 Kommentare
James Tursa
James Tursa am 5 Feb. 2015
@Letian: Not sure what you are asking here. Header files are typically not included on the mex command line since they are explicitly included in your cpp source files via the #include mechanism. MATLAB would not need to recognize it at all ... the compiler itself is the only thing that needs to find and include a header file. (Unless you are using loadlibrary ... which is a separate topic).
James Tursa
James Tursa am 5 Feb. 2015
@Kit: There has to be some other source code or library that has the missing functions in it, since they are not in your source code above. Don't you have any other files?

Melden Sie sich an, um zu kommentieren.

Kategorien

Mehr zu Deploy to C++ Applications Using MATLAB Data API (C++11) finden Sie in Help Center und File Exchange

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!

Translated by