wlan compiled code returns error and i need to specify the password for the ssid - c

I have this code right here I am using mingw to compile and I am running windows XP. When I run the output executable it gives me error prompt about the application..
Do I set everything correctly ? How do I set the SSID password for it to connect ? Also I want to know if I am using the correct network interface to connect (I have an external wifi adapter)..
I got the code from this link any help is very much appreciated..
//#define _WIN32_DCOM
#define _WIN32_WINNT 0x0600
#include <stdio.h>
#include <windows.h>
#include <conio.h>
#include <objbase.h>
#include <rpcsal.h>
#include <objbase.h>
#include <wlanapi.h>
int main(){
PDOT11_SSID pSsid;
strcpy(pSsid->ucSSID, "SUPERONLINE-WiFi_24811");
pSsid->uSSIDLength = 25;
HANDLE wlanHandle;
unsigned long nv;
WlanOpenHandle(1, NULL, &nv, &wlanHandle);
DWORD dwResult = 0;
WLAN_CONNECTION_PARAMETERS cp;
memset(&cp, 0, sizeof(WLAN_CONNECTION_PARAMETERS));
cp.wlanConnectionMode = wlan_connection_mode_profile;
cp.strProfile = NULL;
cp.dwFlags = 0;
cp.pDot11Ssid = pSsid;
cp.pDesiredBssidList = 0;
cp.dot11BssType = dot11_BSS_type_any;
PWLAN_INTERFACE_INFO_LIST pIfList = NULL;
PWLAN_INTERFACE_INFO pIfInfo = NULL;
// only use the first wifi interface
dwResult = WlanEnumInterfaces(wlanHandle, NULL, &pIfList);
pIfInfo = (WLAN_INTERFACE_INFO *)&pIfList->InterfaceInfo[1];
if (dwResult == ERROR_SUCCESS)
{
dwResult = WlanConnect(wlanHandle, &(pIfInfo->InterfaceGuid), &cp, NULL);
if (dwResult == ERROR_SUCCESS)
{
printf("Connected..\n");
//connected = true;
}
}
return 0;
}
This is the error I get:
Edit: I have made it this far to the code below.. But still I can not assign the value to PDOT11_SSID struct.. It seems the struct has UCHAR array yet I can't assign.. Here is the link
PDOT11_SSID pSsid;
UCHAR arr[22] = { 0 };
//memset(pSsid->ucSSID, '\0', 32); //this causes the same error too
memcpy(
arr,
(unsigned char[]){ 'S','U','P','E','R','O','N','L','I','N','E','-','W','i','F','i','_','2','4','8','1','1' },
sizeof(arr)); //memcpy to arr struct works..
ULONG len = 22;
pSsid->uSSIDLength = len;
memcpy(pSsid->ucSSID, arr, sizeof(arr)); // this line fails still..
Edit: I ran with -Wall -Wextra -pedantic -Werror Like David mentioned and with the code segment below:
PDOT11_SSID pSsid;
memset(pSsid->ucSSID, '\0', 32); //fails
I got this error
yet if I initialized with
PDOT11_SSID pSsid = { 0 };
or
PDOT11_SSID pSsid = NULL;
It compiled but I got the crash image above I used to get.. Important to note that memset(pSsid->ucSSID, '\0', 32); causes the crash as well. I can know this by commenting out each line and compiling/running again.
This is a burden since I am yet to figure out how to add SSID password with wlanapi.h so help for these will be much appreciated for me to move on forward.
Fyi: I use basic gcc to compile gcc.exe wlan.c -lwlanapi. If there is any working solution code to connect to an ssid with the ssid and password using wlanapi, a link to that is also appreciated.
Wlan connect from msdn is this link.. I can't see any security parameters, how do I set the password of the SSID I want to connect to ?

Here is what you have been looking for:
#include <winsock2.h>
#include <Wlanapi.h>
#include <iphlpapi.h>
#include <stdio.h>
#pragma warning(disable:4996) /*fuss sprintf*/
#define SSID_MAX_LEN (32)
int ConnectToTargetWifiSSID(char *pSSIDName, char *pPassword)
{
DWORD dwVersion;
#if(0)
DWORD dwMajorVersion;
dwVersion = 0 = dwMajorVersion;
dwVersion = GetVersion();
dwMajorVersion = (DWORD)(LOBYTE(LOWORD(dwVersion)));
DWORD dwClientVersion;
dwClientVersion = ( dwMajorVersion >= 6) ? 2 : 1 ; /*vista or latter*/
#endif
DWORD result;
HANDLE iWifiHandle;
PWLAN_INTERFACE_INFO_LIST iAvailableInterfaces;
PWLAN_AVAILABLE_NETWORK_LIST availableNetworkList;
GUID iInterfaceGuid;
int isHavingProfile;
char authentication[64];
char encryption[64];
int isOpenedAP;
unsigned int i;
unsigned int iii;
WLAN_CONNECTION_PARAMETERS connParam;
iWifiHandle = NULL;
iAvailableInterfaces = NULL;
availableNetworkList = NULL;
/*part zero : one a wlan handle*/
result = WlanOpenHandle(1,NULL,&dwVersion, &iWifiHandle);
if(NULL != iWifiHandle)
{
/*get wireless network card*/
result = WlanEnumInterfaces(iWifiHandle, NULL, &iAvailableInterfaces);
if(ERROR_SUCCESS == result && iAvailableInterfaces->dwNumberOfItems > 0)
{
/*chose the zeroth one*/
printf("InterFaceName: %ls",iAvailableInterfaces->InterfaceInfo[0].strInterfaceDescription);
iInterfaceGuid = iAvailableInterfaces->InterfaceInfo[0].InterfaceGuid;
}
else
{
/*no wireless card*/
result = -2;
goto Exit_ConnectToTargetSSID;
}
}
else
{
result = -1;
goto Exit_ConnectToTargetSSID;
}/*if NULL != iWifiHandle*/
/*part one: scan available wifi routers(SSID)*/
result= WlanGetAvailableNetworkList(iWifiHandle, &iInterfaceGuid,
0x00000001, NULL, &availableNetworkList);
//WLAN_AVAILABLE_NETWORK_INCLUDE_ALL_ADHOC_PROFILES, NULL, &availableNetworkList);
if(ERROR_SUCCESS != result)
return -3;
isHavingProfile = FALSE;
isOpenedAP = FALSE;
iii = -1;
memset(&authentication[0], 0, 64);
memset(&encryption[0], 0, 64);
if( 0 == availableNetworkList->dwNumberOfItems)
{
/*on wifi router has been found*/
result = -4;
goto Exit_ConnectToTargetSSID;
}/*if 0 < wifiList->dwNumberOfItems*/
for(i = 0; i < availableNetworkList->dwNumberOfItems; i++)
{
DWORD flag;
printf("SSID:\t\t\t%s\nSIGNAL:\t\t\t%d\n",
availableNetworkList->Network[i].dot11Ssid.ucSSID,
availableNetworkList->Network[i].wlanSignalQuality);
printf("SECURITY:\t\t");
switch(availableNetworkList->Network[i].dot11DefaultAuthAlgorithm)
{
case DOT11_AUTH_ALGO_80211_OPEN:
printf("OPEN\n");
break;
case DOT11_AUTH_ALGO_80211_SHARED_KEY:
printf("WEP\n");
break;
case DOT11_AUTH_ALGO_WPA:
case DOT11_AUTH_ALGO_WPA_PSK:
case DOT11_AUTH_ALGO_WPA_NONE:
printf("WPA\n");
break;
case DOT11_AUTH_ALGO_RSNA:
case DOT11_AUTH_ALGO_RSNA_PSK:
printf("WPA2\n");
break;
default:
printf("UNKNOWN\n");
break;
}
printf("encryption:\t\t");
switch(availableNetworkList->Network[i].dot11DefaultCipherAlgorithm)
{
case DOT11_CIPHER_ALGO_NONE:
printf("NONE\n");
break;
case DOT11_CIPHER_ALGO_WEP40:
printf("WEP40\n");
break;
case DOT11_CIPHER_ALGO_TKIP:
printf("TKIP\n");
break;
case DOT11_CIPHER_ALGO_WEP104:
printf("WEP104\n");
break;
case DOT11_CIPHER_ALGO_CCMP:
printf("CCMP\n");
break;
default:
printf("UNKNOWN\n");
break;
}/*switch*/
flag = availableNetworkList->Network[i].dwFlags;
if(flag & 0x00000001)
printf("\t NOTE : Current connecting\n");
if(flag & 0x00000002)
printf("\t NOTE : WLAN_AVAILABLE_NETWORK_HAS_PROFILE\n");
if(flag & 0x00000004)
printf("\t NOTE : WLAN_AVAILABLE_NETWORK_CONSOLE_USER_PROFILE\n");
/*if(flag & WLAN_AVAILABLE_NETWORK_CONNECTED)
printf("\t NOTE : Current connecting\n");
if(flag & WLAN_AVAILABLE_NETWORK_HAS_PROFILE)
printf("\t NOTE : WLAN_AVAILABLE_NETWORK_HAS_PROFILE\n");
if(flag & WLAN_AVAILABLE_NETWORK_CONSOLE_USER_PROFILE)
printf("\t NOTE : WLAN_AVAILABLE_NETWORK_CONSOLE_USER_PROFILE\n");*/
printf("\n");
}/*for */
/*part two: save target SSID propertis*/
for(i = 0; i < availableNetworkList->dwNumberOfItems; i++)
{
if(0 == strncmp(pSSIDName, (char*)availableNetworkList->Network[i].dot11Ssid.ucSSID , SSID_MAX_LEN))
{
//WLAN_AVAILABLE_NETWORK_CONNECTED
if( 0x00000001 & availableNetworkList->Network[i].dwFlags)
{
printf("%s is current connecting!!\n", pSSIDName);
result = 1;
goto Exit_ConnectToTargetSSID;
}/*if*/
iii = i;
if(0x00000002 & availableNetworkList->Network[i].dwFlags)
//if(WLAN_AVAILABLE_NETWORK_HAS_PROFILE & availableNetworkList->Network[i].dwFlags)
isHavingProfile = TRUE;
/*list the target SSID properties*/
switch(availableNetworkList->Network[i].dot11DefaultAuthAlgorithm)
{
case DOT11_AUTH_ALGO_80211_OPEN:
sprintf(&authentication[0], "OPEN");
break;
case DOT11_AUTH_ALGO_80211_SHARED_KEY:
sprintf(&authentication[0], "WEP");
break;
case DOT11_AUTH_ALGO_WPA:
case DOT11_AUTH_ALGO_WPA_PSK:
case DOT11_AUTH_ALGO_WPA_NONE:
sprintf(&authentication[0], "WPAPSK");
break;
case DOT11_AUTH_ALGO_RSNA:
case DOT11_AUTH_ALGO_RSNA_PSK:
sprintf(&authentication[0], "WPA2PSK");
break;
default:
sprintf(&authentication[0], "UNKNOWN");
break;
}/*switch dot11DefaultAuthAlgorithm*/
switch(availableNetworkList->Network[i].dot11DefaultCipherAlgorithm)
{
case DOT11_CIPHER_ALGO_NONE:
sprintf(&encryption[0], "NOEN");
break;
case DOT11_CIPHER_ALGO_TKIP:
sprintf(&encryption[0], "TKIP");
break;
case DOT11_CIPHER_ALGO_CCMP:
sprintf(&encryption[0], "AES");
break;
default:
sprintf(&encryption[0], "WEP");
break;
}/*/*switch dot11DefaultCipherAlgorithm*/
break;
}/*if 0 == strncmp(pSSIDName, (char*)availableNetworkList->Network[i].dot11Ssid.ucSSID , SSID_MAX_LEN)*/
}/*for i*/
if(-1 == iii)
{
/*target router could not found */
result = -5;
goto Exit_ConnectToTargetSSID;
}/*if */
/*part there, set XML profile*/
if(FALSE == isHavingProfile)
{
/*if current computer has never connected to target router..*/
wchar_t profileXMLUnicode[4096];
char buff[4096];
DWORD reasonCode;
char profileTemplateXML[] = "<?xml version=\"1.0\"?>" \
"<WLANProfile xmlns=\"http://www.microsoft.com/networking/WLAN/profile/v1\">"\
" <name>%s</name>" \
" <SSIDConfig> " \
" <SSID>" \
" <name>%s</name>"\
" </SSID>"\
" </SSIDConfig>"\
" <connectionType>ESS</connectionType>"\
" <connectionMode>auto</connectionMode>"\
" <MSM>"\
" <security>"\
" <authEncryption>"\
" <authentication>%s</authentication>"\
" <encryption>%s</encryption>"\
" <useOneX>false</useOneX>"\
" </authEncryption>"\
" <sharedKey>"\
" <keyType>passPhrase</keyType>"\
" <protected>false</protected>"\
" <keyMaterial>%s</keyMaterial>"\
" </sharedKey>"\
" </security>" \
" </MSM>" \
"</WLANProfile>" ;
reasonCode = 0;
sprintf(buff, profileTemplateXML, availableNetworkList->Network[iii].dot11Ssid.ucSSID,
availableNetworkList->Network[iii].dot11Ssid.ucSSID,
&authentication[0], &encryption[0], pPassword);
/*Covert ansi to unicode*/
MultiByteToWideChar(CP_ACP, 0, &buff[0], -1, &profileXMLUnicode[0], 4096);
result = WlanSetProfile(iWifiHandle, &iInterfaceGuid, 0, &profileXMLUnicode[0],
NULL, TRUE, NULL, &reasonCode);
wprintf( L"%s", profileXMLUnicode);
if(ERROR_SUCCESS != result)
{
result = -6;
goto Exit_ConnectToTargetSSID;
}/*if */
}
else
{
/*if current computer had connected to target router, and remember who it is ...*/
DWORD dwFlags;
DWORD dwGrantedAccess;
LPWSTR xml;
result = WlanGetProfile(iWifiHandle, &iInterfaceGuid,
availableNetworkList->Network[iii].strProfileName, NULL, &xml ,&dwFlags,&dwGrantedAccess);
wprintf( L"%s", xml);
}/*if FASLSE == isHavingProfile*/
/*part four, connect to target ssid */
connParam.pDot11Ssid= NULL;
connParam.strProfile= availableNetworkList->Network[iii].strProfileName;
connParam.wlanConnectionMode = wlan_connection_mode_profile;
connParam.pDesiredBssidList=NULL;
connParam.dot11BssType= availableNetworkList->Network[iii].dot11BssType;
connParam.dwFlags = 0;
//wprintf( L"%s", &iInterfaceGuid,wifiList->Network[iii].strProfileName);
result = WlanConnect(iWifiHandle, &iInterfaceGuid, &connParam, NULL);
if(ERROR_SUCCESS != result)
result = -7;
Exit_ConnectToTargetSSID:
if(NULL != availableNetworkList)
WlanFreeMemory(availableNetworkList);
if(NULL != iAvailableInterfaces)
WlanFreeMemory(iAvailableInterfaces);
if(NULL != iWifiHandle)
WlanCloseHandle(iWifiHandle, NULL);
return result;
}/*ConnectToTargetWifiSSID*/
int main(int argc, char *argv[])
{
ConnectToTargetWifiSSID("SUPERONLINE-WiFi_24811", "pass123");
return 0;
}/*main*/

Related

PrintDlgEx fails with "Invalid Argument"

I am Working with Win32 API and C.
I need to get supported page sizes of my system default printer.
Referring to DeviceCapabilities of a network printer on this forum (which suggested PrintDlg), I am trying to use PrintDlgEx, with Flags=PD_RETURNDEFAULT.
My problem is, call to PrintDlgEx fails with error "E_INVALIDARG", ie, Invalid Argument.
I have written the code as a console program.
Can some one help me identify what is going wrong.
My code is pasted below
int main(void)
{
HWND Myhwnd = GetConsoleWindow();
if (Myhwnd == NULL)
printf("GetConsoleWindow Failed \n");
PRINTDLGEX pdlg;
memset(&pdlg, 0, sizeof(PRINTDLGEX));
pdlg.lStructSize = sizeof(PRINTDLGEX);
pdlg.hwndOwner = Myhwnd;
pdlg.Flags = PD_RETURNDEFAULT|| PD_NOPAGENUMS;
pdlg.nCopies = 1;
pdlg.nPropertyPages = 0;
pdlg.dwResultAction = 0;
pdlg.nStartPage = START_PAGE_GENERAL;
HRESULT result = PrintDlgEx(&pdlg);
switch (result)
{
... ...
case E_INVALIDARG:
printf("Invalid Argument\n");
break;
}
return 0;
}
I noticed in PrintDlgEx documentation it says "This structure must be declared dynamically using a memory allocation function.". So I changed my program as below, but still gives same error "Invalid Argument".
int main(void)
{
HWND Myhwnd = GetConsoleWindow();
if (Myhwnd == NULL)
printf("GetConsoleWindow Failed \n");
PRINTDLGEX * pdlg;
pdlg = malloc(sizeof(PRINTDLGEX));
memset(pdlg, 0, sizeof(PRINTDLGEX));
pdlg->lStructSize = sizeof(PRINTDLGEX);
pdlg->hwndOwner = Myhwnd;
pdlg->Flags = PD_RETURNDEFAULT|| PD_NOPAGENUMS;
pdlg->nCopies = 1;
pdlg->nPropertyPages = 0;
pdlg->dwResultAction = 0;
pdlg->nStartPage = START_PAGE_GENERAL;
HRESULT result = PrintDlgEx(pdlg);
switch (result)
{
... ...
case E_INVALIDARG:
printf("Invalid Argument\n");
break;
}
return 0;
}
I have checked your code with MSVC2019. As IInspectable said in a comment, the error is the use of boolean or || operator instead of bitwise or |operator.
I also checked that the call work with a statically allocated PRINTDLGEX variable or a dynamically allocated one.
The code is:
#include <stdio.h>
#include <stdlib.h>
#include <windows.h>
int main(void)
{
HWND Myhwnd = GetConsoleWindow();
if (Myhwnd == NULL)
printf("GetConsoleWindow Failed \n");
PRINTDLGEX pdlg;
memset(&pdlg, 0, sizeof(PRINTDLGEX));
pdlg.lStructSize = sizeof(PRINTDLGEX);
pdlg.hwndOwner = Myhwnd;
pdlg.Flags = PD_RETURNDEFAULT | PD_NOPAGENUMS;
pdlg.nCopies = 1;
pdlg.nPropertyPages = 0;
pdlg.dwResultAction = 0;
pdlg.nStartPage = START_PAGE_GENERAL;
HRESULT result = PrintDlgEx(&pdlg);
switch (result)
{
case S_OK:
printf("Success\n");
break;
case E_INVALIDARG:
printf("Invalid Argument\n");
break;
default:
printf("Error %d\n", result);
break;
}
return 0;
}

Mex type C file to normal C file

I have a c file written using mex functions, run by Matlab using mex compiler Now I want to run those mex type .c files without Matlab environment. So, is there any way to convert mex type .c file to normal .c file ? Or any other options available for the above mentioned concern.
Thanks in advance....!
Here is the one mex type .c file for sample.
#include <stdlib.h>
#include "mex.h"
#include "matrix.h"
#include "distances.h"
#include "ltl2tree.h"
#include "param.h"
#define BUFF_LEN 4096
char * emalloc(size_t n)
{
char *tmp;
if (!(tmp = (char *) mxMalloc(n)))
mexErrMsgTxt("mx_dp_taliro: not enough memory!");
memset(tmp, 0, n);
return tmp;
}
int tl_Getchar(int *cnt, size_t hasuform, char *uform)
{
if (*cnt < hasuform)
return uform[(*cnt)++];
(*cnt)++;
return -1;
}
void tl_UnGetchar(int *cnt)
{
if (*cnt > 0) (*cnt)--;
}
#define Binop(a) \
fprintf(miscell->tl_out, "("); \
dump(n->lft, miscell); \
fprintf(miscell->tl_out, a); \
dump(n->rgt, miscell); \
fprintf(miscell->tl_out, ")")
static void sdump(Node *n, char *dumpbuf)
{
switch (n->ntyp) {
case PREDICATE: strcat(dumpbuf, n->sym->name);
break;
case U_OPER: strcat(dumpbuf, "U");
goto common2;
case V_OPER: strcat(dumpbuf, "V");
goto common2;
case OR: strcat(dumpbuf, "|");
goto common2;
case AND: strcat(dumpbuf, "&");
common2: sdump(n->rgt,dumpbuf);
common1: sdump(n->lft,dumpbuf);
break;
case NEXT: strcat(dumpbuf, "X");
goto common1;
case NOT: strcat(dumpbuf, "!");
goto common1;
case TRUE: strcat(dumpbuf, "T");
break;
case FALSE: strcat(dumpbuf, "F");
break;
default: strcat(dumpbuf, "?");
break;
}
}
Symbol *DoDump(Node *n, char *dumpbuf, Miscellaneous *miscell)
{
if (!n) return ZS;
if (n->ntyp == PREDICATE)
return n->sym;
dumpbuf[0] = '\0';
sdump(n,dumpbuf);
return tl_lookup(dumpbuf, miscell);
}
void dump(Node *n, Miscellaneous *miscell)
{
if (!n) return;
switch(n->ntyp) {
case OR: Binop(" || "); break;
case AND: Binop(" && "); break;
case U_OPER: Binop(" U "); break;
case V_OPER: Binop(" V "); break;
case NEXT:
fprintf(miscell->tl_out, "X");
fprintf(miscell->tl_out, " (");
dump(n->lft, miscell);
fprintf(miscell->tl_out, ")");
break;
case NOT:
fprintf(miscell->tl_out, "!");
fprintf(miscell->tl_out, " (");
dump(n->lft, miscell);
fprintf(miscell->tl_out, ")");
break;
case FALSE:
fprintf(miscell->tl_out, "false");
break;
case TRUE:
fprintf(miscell->tl_out, "true");
break;
case PREDICATE:
fprintf(miscell->tl_out, "(%s)", n->sym->name);
break;
case -1:
fprintf(miscell->tl_out, " D ");
break;
default:
printf("Unknown token: ");
tl_explain(n->ntyp);
break;
}
}
void tl_explain(int n)
{
switch (n) {
case ALWAYS: printf("[]"); break;
case EVENTUALLY: printf("<>"); break;
case IMPLIES: printf("->"); break;
case EQUIV: printf("<->"); break;
case PREDICATE: printf("predicate"); break;
case OR: printf("||"); break;
case AND: printf("&&"); break;
case NOT: printf("!"); break;
case U_OPER: printf("U"); break;
case V_OPER: printf("V"); break;
case NEXT: printf("X"); break;
case TRUE: printf("true"); break;
case FALSE: printf("false"); break;
case ';': printf("end of formula"); break;
default: printf("%c", n); break;
}
}
static void non_fatal(char *s1, char *s2, int *cnt, char *uform, int *tl_yychar, Miscellaneous *miscell)
{
int i;
printf("TaLiRo: ");
if (s2)
printf(s1, s2);
else
printf(s1);
if ((*tl_yychar) != -1 && (*tl_yychar) != 0)
{ printf(", saw '");
tl_explain((*tl_yychar));
printf("'");
}
printf("\nTaLiRo: %s\n---------", uform);
for (i = 0; i < (*cnt); i++)
printf("-");
printf("^\n");
fflush(stdout);
(miscell->tl_errs)++;
}
void
tl_yyerror(char *s1, int *cnt, char *uform, int *tl_yychar, Miscellaneous *miscell)
{
Fatal(s1, (char *) 0, cnt, uform, tl_yychar, miscell);
}
void
Fatal(char *s1, char *s2, int *cnt, char *uform, int *tl_yychar, Miscellaneous *miscell)
{
non_fatal(s1, s2, cnt, uform, tl_yychar, miscell);
tl_exit(0);
}
void fatal(char *s1, char *s2, int *cnt, char *uform, int *tl_yychar, Miscellaneous *miscell)
{
non_fatal(s1, s2, cnt, uform, tl_yychar, miscell);
tl_exit(0);
}
void put_uform(char *uform, Miscellaneous *miscell)
{
fprintf(miscell->tl_out, "%s", uform);
}
void tl_exit(int i)
{
mexErrMsgTxt("mx_dp_taliro: unexpected error, tl_exit executed.");
}
void mexFunction(int nlhs, mxArray *plhs[],int nrhs, const mxArray *prhs[])
{
/* Variables needed to process the input */
int status, pstatus;
mwSize buflen, pbuflen;
size_t NElems,NCells;
mwSize ndimA, ndimb, ndimG, ndim, pdim,ndimP;
const mwSize *dimsA, *dimsb, *dimsG, *dims, *pardims,*dimsP;
mwIndex jstruct, iii, jjj, i1, j1, idx_j;
mxArray *tmp,*tmp1,*tmp_cell;
/* Variables needed for monitor */
Node *node;
double *XTrace, *TStamps, *LTrace;
DistCompData distData;
PMap *predMap;
int ii,jj,kk,ll,objs,tempI;
bool par_on;
bool is_Multi_HA;
bool initial_of_par;
int npred, npar;
static char uform[BUFF_LEN];
static size_t hasuform=0;
static int *cnt;
int temp = 0;
Miscellaneous *miscell = (Miscellaneous *) emalloc(sizeof(Miscellaneous));
int *tl_yychar = (int *) emalloc(sizeof(int));
miscell->dp_taliro_param.LTL = 1;
miscell->dp_taliro_param.ConOnSamples = 0;
miscell->dp_taliro_param.SysDim = 0;
miscell->dp_taliro_param.nSamp = 0;
miscell->dp_taliro_param.nPred = 0;
miscell->dp_taliro_param.true_nPred = 0;
miscell->dp_taliro_param.tnLoc = 0;
miscell->dp_taliro_param.nInp = 0;
miscell->dp_taliro_param.nCLG = 0;
miscell->tl_errs = 0;
miscell->type_temp = 0;
/* Reset cnt to 0:
cnt is the counter that points to the next symbol in the formula
to be processed. This is a static variable and it retains its
value between Matlab calls to mx_dp_taliro. */
cnt = &temp;
/* Other initializations */
miscell->dp_taliro_param.nInp = nrhs;
par_on = false;
initial_of_par = false;
npred = 0;
npar= 0;
/* Make sure the I/O are in the right form */
if(nrhs < 3)
mexErrMsgTxt("mx_dp_taliro: At least 3 inputs are required.");
else if(nlhs > 1)
mexErrMsgTxt("mx_dp_taliro: Too many output arguments.");
else if(nrhs > 8)
mexErrMsgTxt("mx_dp_taliro: Too many input arguments.");
else if(!mxIsChar(prhs[0]))
mexErrMsgTxt("mx_dp_taliro: 1st input must be a string with TL formula.");
else if(!mxIsStruct(prhs[1]))
mexErrMsgTxt("mx_dp_taliro: 2nd input must be a structure (predicate map).");
else if(!mxIsDouble(prhs[2]))
mexErrMsgTxt("mx_dp_taliro: 3rd input must be a numerical array (State trace).");
else if(nrhs>3 && !mxIsDouble(prhs[3]))
mexErrMsgTxt("mx_dp_taliro: 4th input must be a numerical array (Time stamps).");
else if(nrhs>5 && !mxIsDouble(prhs[4]))
mexErrMsgTxt("mx_dp_taliro: 5th input must be a numerical array (Location trace).");
else if(nrhs>5 && !(mxIsDouble(prhs[5])||mxIsCell(prhs[5])))
mexErrMsgTxt("mx_dp_taliro: 6th input must be a numerical array \n (Minimum path distance to each control location for each predicate).");
else if(nrhs>7 && !(mxIsCell(prhs[6])))
mexErrMsgTxt("mx_dp_taliro: 7th input must be a cell array (Adjacency list).");
else if(nrhs>7 && !(mxIsStruct(prhs[7])||mxIsCell(prhs[7])))
mexErrMsgTxt("mx_dp_taliro: 8th input must be a structure (guard map).");
if(nlhs > 1)
mexErrMsgTxt("Too many output arguments.");
plhs[0] = mxCreateDoubleMatrix(1,1,mxREAL);
/* Process inputs */
/* Get the formula */
ndim = mxGetNumberOfDimensions(prhs[0]);
dims = mxGetDimensions(prhs[0]);
buflen = dims[1]*sizeof(mxChar)+1;
if (buflen >= BUFF_LEN)
{
mexPrintf("%s%d%s\n", "The formula must be less than ", BUFF_LEN," characters.");
mexErrMsgTxt("mx_dp_taliro: Formula too long.");
}
status = mxGetString(prhs[0], uform, buflen);
hasuform = strlen(uform);
for (iii=0; iii<hasuform; iii++)
{
if (uform[iii] == '\t' || uform[iii] == '\"' || uform[iii] == '\n')
uform[iii] = ' ';
}
/* Get state trace */
ndim = mxGetNumberOfDimensions(prhs[2]);
if (ndim>2)
mexErrMsgTxt("mx_dp_taliro: The state trace is not in proper form!");
dims = mxGetDimensions(prhs[2]);
miscell->dp_taliro_param.nSamp = dims[0];
miscell->dp_taliro_param.SysDim = dims[1];
XTrace = mxGetPr(prhs[2]);
/* Get time stamps */
if (nrhs>3)
{
ndim = mxGetNumberOfDimensions(prhs[3]);
if (ndim>2)
mexErrMsgTxt("mx_dp_taliro: The time stamp sequence is not in proper form!");
dims = mxGetDimensions(prhs[3]);
if (miscell->dp_taliro_param.nSamp != dims[0])
mexErrMsgTxt("mx_dp_taliro: The lengths of the time stamp sequence and the state trace do not match!");
TStamps = mxGetPr(prhs[3]);
}
/* Get location trace and location graph */
if (nrhs>4)
{
ndim = mxGetNumberOfDimensions(prhs[4]);
if (ndim>2)
mexErrMsgTxt("mx_dp_taliro: The location trace is not in proper form!");
dims = mxGetDimensions(prhs[4]);
if (miscell->dp_taliro_param.nSamp != dims[0])
mexErrMsgTxt("mx_dp_taliro: The lengths of the location trace and the state trace do not match!");
LTrace = mxGetPr(prhs[4]);
/* For Multiple H.A.s is added */
if(nrhs>5 && (mxIsCell(prhs[5]))){/* For Multiple H.A.s */
is_Multi_HA=1;
miscell->dp_taliro_param.nCLG = dims[1];
ndim = mxGetNumberOfDimensions(prhs[5]);
if (ndim>2)
{
mexErrMsgTxt("mx_dp_taliro.c: !");
}
dims = mxGetDimensions(prhs[5]);
if (dims[0]!=1)
{
mexErrMsgTxt("mx_dp_taliro: DMin is a cell, it must be a column vector cell!");
}
if (dims[1]!=miscell->dp_taliro_param.nCLG)
{
mexErrMsgTxt("mx_dp_taliro: DMin is a cell, it must be of the size of nCLG!");
}
distData.LDistNCLG = (double **)emalloc((miscell->dp_taliro_param.nCLG)*sizeof(double*));
miscell->dp_taliro_param.tnLocNCLG = (mwSize*)emalloc((miscell->dp_taliro_param.nCLG)*sizeof(mwSize));
for(kk=0; kk<miscell->dp_taliro_param.nCLG; kk++){
tmp = mxGetCell(prhs[5],kk);
dims = mxGetDimensions(tmp);
miscell->dp_taliro_param.tnLocNCLG[kk] = dims[0];
distData.LDistNCLG[kk]=mxGetPr(tmp);
}
}
else if(nrhs>5) {/* For Single H.A. */
is_Multi_HA=0;
ndim = mxGetNumberOfDimensions(prhs[5]);
if (ndim>2)
mexErrMsgTxt("mx_dp_taliro: The minimum distance array is not in proper form!");
dims = mxGetDimensions(prhs[5]);
miscell->dp_taliro_param.tnLoc = dims[0];
distData.LDist = mxGetPr(prhs[5]);
}
}
}
In your code, you are using a lot of functions and data types, provided by the MEX API. Therefore, if you want to produce "normal" C-Code you will have to completly refactor your code.
But one possible solution might be to compile your source code outside MATLAB IDE, by gcc or any other compiler. In this case you will have to include all necessary header files and link against all libraries you need.
Follwo the link to find a pretty good documentation from Mathworks:
https://de.mathworks.com/matlabcentral/answers/377799-compiling-mex-files-without-the-mex-command
Another way for creating C Code from Matlab Scipts/Functions is to use MATLAB Coder:
https://de.mathworks.com/products/matlab-coder.html
Hope this is helpful.

Commands to execute functions in C

I'm using the LXLE 14.04 distribution of Linux.
I want to write a C program to read commands, interpret and perform them. I'd like the program to be efficient, and I do not want to use
a linked list.
The commands are operations on sets.
Each set can contain any of the values from 0 through 127 inclusive.
I decided to represent a set as an array of characters, containing 128 bits.
If bit at position pos is turned on then the number pos is in the set and if the bit at position pos is turned off then the number pos is
not present in the set. For example, if the bit at position 4 is 1, then the number 4 is present in the set, if the bit at position 11 is 1 then the number
11 is present in the set.
The program should read commands and interpret them in a certain way.
There are a few commands: read_set, print_set, union_set, intersect_set, sub_set and halt.
For example, the command read_set A,1,2,14,-1 in the terminal will cause the reading of values of the list into the specified set in the command.
In this case the specified set in the command is A. The end of the list is represented by -1. So after writing this command, the set A will contain the elements 1,2,14.
This is what I have so far.
Below is the file set.h
#include <stdio.h>
typedef struct
{
char array[16]; /*Takes 128 bits of storage*/
}set;
extern set A , B , C , D , E , F;
This is the file main.c
#include <stdio.h>
#include "set.h"
#include <string.h>
#include <stdlib.h>
set A , B , C , D , E , F; /*Variable definition*/
void read_set(set s,char command[])
{
int i, number = 0 , pos;
char* str_num = strtok(NULL,"A, ");
unsigned int flag = 1;
printf("I am in the function read_set right now\n");
while(str_num != NULL) /*without str_num != NULL get segmentation fault*/
{
number = atoi(str_num);
if(number == -1)
return;
printf("number%d ",number);
printf("str_num %c\n",*str_num);
i = number/8; /*Array index*/
pos = number%8; /*bit position*/
flag = flag << pos;
s.array[i] = s.array[i] | flag;
str_num = strtok(NULL, ", ");
if(s.array[i] & flag)
printf("Bit at position %d is turned on\n",pos);
else
printf("Bit at position %d is turned off\n",pos);
flag = 1;
}
}
void print_set(set s)
{
unsigned int flag = 1; int in_set = 0;
int i = 0;
while(s.array[i] != -1)
{
if(s.array[i] & flag)
{
in_set = s.array[i];
printf("%d,",in_set );
}
i++;
flag = 1;
}
}
int main()
{
#define CMD_LENGTH 256
char command[CMD_LENGTH]; char* letter;
printf("Please enter a command");
gets(command);
letter = strtok(command,"read_set ,");
switch(*letter)
{
case 'A':
{
read_set(A,command);
break;
}
case 'B':
{
read_set(B,command);
break;
}
case 'C':
{
read_set(C,command);
break;
}
case 'D':
{
read_set(D,command);
break;
}
case 'E':
{
read_set(E,command);
break;
}
case 'F':
{
read_set(F,command);
break;
}
}
return 0;
}
Clearly, it is not a good practice to write a bunch of switch statements and using strtok for each command, and repeating the code written in the main function for each command in order to call the different functions. I thought about using a pointer to a generic function, but since each function receives different parameters,
I do not think this is going to work.
Is there a better way of doing this?
Thanks in advance!
Update #1:
Here's the code. I've made some changes to it.
#include <stdio.h>
#include "set.h"
#include <string.h>
#include <stdlib.h>
set A , B , C , D , E , F; /*Variable definition*/
set sets[6];
/*Below I want to initialize sets so that set[0] = A set[1] = B etc*/
sets[0].array = A.array;
sets[1].array = B.array;
sets[2].array = C.array;
sets[3].array = D.array;
sets[4].array = E.array;
sets[5].array = F.array;
void read_set(set s,char all_command[])
{
int i, number = 0 , pos;
char* str_num = strtok(NULL,"A, ");
unsigned int flag = 1;
printf("I am in the function read_set right now\n");
while(str_num != NULL) /*without str_num != NULL get segmentation fault*/
{
number = atoi(str_num);
if(number == -1)
return;
printf("number%d ",number);
printf("str_num %c\n",*str_num);
i = number/8; /*Array index*/
pos = number%8; /*bit position*/
flag = flag << pos;
s.array[i] = s.array[i] | flag;
str_num = strtok(NULL, ", ");
if(s.array[i] & flag)
printf("Bit at position %d is turned on\n",pos);
else
printf("Bit at position %d is turned off\n",pos);
flag = 1;
}
}
typedef struct
{
char *command;
void (*func)(set,char*);
} entry;
entry chart[] = { {"read_set",&read_set} };
void (*getFunc(char *comm) ) (set,char*)
{
int i;
for(i=0; i<2; i++)
{
if( strcmp(chart[i].command,comm) == 0)
return chart[i].func;
}
return NULL;
}
int main()
{
#define PER_CMD 256
char all_comm[PER_CMD]; void (*ptr_one)(set,char*) = NULL; char* comm; char* letter;
while( (strcmp(all_comm,"halt") != 0 ) & (all_comm != NULL))
{
printf("Please enter a command");
gets(all_comm);
comm = strtok(all_comm,", ");
ptr_one = getFunc(comm);
letter = strtok(NULL,",");
ptr_one(A,all_comm);
all_comm[0] = '\0';
letter[0] = '\0';
}
return 0;
}
I get the following compile error:
main.c:9:8: error: expected ���=���, ���,���, ���;���, ���asm��� or ���attribute��� before ���.��� token
What's my mistake? How can I fix this?
Thanks a lot! #Claim Yang
However,in your case, using switch is almost the best solution to this.
Another way without switch is using a simple way to get an index. Here is a simple solution.
set sets[6];
read_set(sets[*letter - 'A'], command);
Then if you need to read a command, another array of pointers to functions is needed. Like below:
void (*functions[3])(set,char[]);
functions[0] = read_set;
And so on.
The point is coverting your string to an int, so it can be seen as an index of an array.
Then call functions like functions[string_to_int(string)](set,char[]);

Missing events on ReadConsoleInput in windows shell?

As I proceed in my (possibly vain) attempt to reimplement a curses style library that supports both *nix and windows under an MIT license, I've stumbled onto a problem reading terminal import using the windows api.
Basically, I don't get all the events I expect to, and I don't know why.
First I setup the terminal to be in non-buffering mode:
DWORD mode;
HANDLE hstdin = GetStdHandle( STD_INPUT_HANDLE );
// Save old mode
GetConsoleMode(hstdin, &mode);
// Set to no line-buffering, no echo, no special-key-processing
SetConsoleMode(hstdin, 0);
Then I use PeekConsoleInput and ReadConsoleInput in a loop to have a non blocking key press input; the equivalent of using termios.h and select on stdin in linux:
__EXPORT int sterm_read(void *state) {
DWORD dwRead;
INPUT_RECORD inRecords[1];
PeekConsoleInput(GetStdHandle(STD_INPUT_HANDLE), &inRecords[0], 1, &dwRead);
if (dwRead > 0) {
ReadConsoleInput(GetStdHandle(STD_INPUT_HANDLE), &inRecords[0], 1, &dwRead);
if (inRecords[0].EventType == KEY_EVENT) {
if (inRecords[0].Event.KeyEvent.bKeyDown) {
return inRecords[0].Event.KeyEvent.wVirtualKeyCode;
}
}
}
return -1;
}
Ignore the state variable; that's so the api can accept an arbitrary state struct on various platforms.
Now if I try to use this code:
#include <sterm.h>
#include <stdio.h>
#define assert(v, msg) if (!v) { printf("FAILED! %s", msg); return 1; }
int main(void) {
void *state = sterm_init();
int i;
char c;
for (;;) {
if ((c = sterm_read(state)) == 81) { // ie. press q to exit
break;
}
if (c != -1) {
sterm_write(state, &c, 1); // This is a thin wrapper around _write(1, ...)
}
}
sterm_shutdown(state);
return 0;
}
It almost works. I get the input character I press pushed out to the terminal... mostly.
Probably every 10th character press is recorded. If I type quickly, the API 'loses' events, and I get "HEO WLD" instead of "HELLO WORLD".
What's going on? Does ReadConsoleInput somehow clear the input buffer?
Am I doing something wrong? It seems almost like I'm only getting events based on a race condition which is 'is key pressed when PeekConsoleInput is called'.
...but surely that shouldn't be the case? The point of using these buffered I/O interfaces (instead of GetAsyncKeyState) is that the events should be buffered right?
Help!
I also have discovered that events are not guaranteed to stay around to be read.
This makes sense because otherwise the OS would need to provide lots and lots of buffering space.
The best I can do to deal with this is this code to do my own buffering
but clearly pastes of more than 128 characters will often fail :
static int g_eaten_ct = 0; /* Re-eaten char */
static int g_eaten_ix = -1;
static int g_eaten[128];
void reeat(int c)
{ g_eaten_ct += 1;
g_eaten[g_eaten_ix + g_eaten_ct] = c; /* save the char for later */
}
void flush_typah()
{
g_eaten_ct = 0;
g_eaten_ix = -1;
while (_kbhit())
(void)ttgetc();
}
int ttgetc()
{ if (g_eaten_ct > 0)
{ g_eaten_ct -= 1;
return g_eaten[++g_eaten_ix];
}
{ int totalwait = g_timeout_secs;
int oix = -1;
while (1)
{ int got,need;
const DWORD lim = 1000;
INPUT_RECORD rec[32];
int cc = WaitForSingleObject(g_ConsIn, lim);
switch(cc)
{ case WAIT_OBJECT_0:
need = sizeof(g_eaten)/sizeof(g_eaten[0]) - oix;
if (need > 32)
need = 32;
cc = ReadConsoleInput(g_ConsIn,&rec[0],need,(DWORD*)&got);
if (cc && got > 0)
break;
#if _DEBUG
{ DWORD errn = GetLastError();
if (errn != 6)
mlwrite("%pError %d %d ", cc, errn);
}
#endif
continue;
case WAIT_TIMEOUT:
#if _DEBUG
if (g_got_ctrl)
{ g_got_ctrl = false;
return (int)(CTRL | 'C');
}
#endif
if (--totalwait == 0) // -w opt
exit(2);
// drop through
default:continue;
}
{ int ix = -1;
while (++ix < got)
{ INPUT_RECORD * r = &rec[ix];
if (r->EventType == KEY_EVENT && r->Event.KeyEvent.bKeyDown)
{ int ctrl = 0;
int keystate = r->Event.KeyEvent.dwControlKeyState;
if (keystate & (RIGHT_CTRL_PRESSED | LEFT_CTRL_PRESSED))
{ ctrl |= CTRL;
g_chars_since_ctrl = 0;
}
{ int chr = r->Event.KeyEvent.wVirtualKeyCode;
if (in_range(chr, 0x10, 0x12))
continue; /* shifting key only */
if (keystate & (RIGHT_ALT_PRESSED | LEFT_ALT_PRESSED))
ctrl |= ALTD;
else
chr = r->Event.KeyEvent.uChar.AsciiChar & 0xff;
if (/*chr != 0x7c && */ (chr | 0x60) != 0x7c) // | BSL < or ^ BSL
{ int vsc = r->Event.KeyEvent.wVirtualScanCode;
if (in_range(vsc, SCANK_STT, 0x58))
{ ctrl |= SPEC;
chr = scantokey[vsc - SCANK_STT];
}
// else if (in_range(vsc, 2, 10) && chr == 0)
// chr = '0' - 1 + vsc;
}
if ((keystate & SHIFT_PRESSED) && ctrl) // exclude e.g. SHIFT 7
ctrl |= SHFT;
g_eaten[++oix] = ctrl | (chr == 0xdd ? 0x7c : chr);
++g_chars_since_ctrl;
}}
else if (r->EventType == MENU_EVENT)
{ /*loglog1("Menu %x", r->Event.MenuEvent.dwCommandId);*/
}
}
if (got == need && oix < sizeof(g_eaten) / sizeof(int))
{ PeekConsoleInput(g_ConsIn, &rec[0], 1, (DWORD*)&got);
if (got > 0)
continue;
}
if (oix >= 0)
{ g_eaten_ct = oix;
g_eaten_ix = 0;
return g_eaten[0];
}
}}
}}

transferring from PLC (OPC client server Kepware) to MS Access, C

I am completely new to working with PLCs, but I have a project that need fetch data from an OPC client server, then send it to an Access database table. The bulk of the code minus OPCWriteGroupItems was from someone else. I am just lost on transferring the data that the get from OPCReadGroupItems to the proper variables in my function OPCWriteGroupItems. I just want to get the values that are read into the variables. Thanks.
F.Y.I.
My query statement I know needs to be tweaked so that it will read the variables correctly but that is anouther problem that I am working on. This is the more pressing concern.
Below are the two functions that I spoke of:
//---------------------------------------------------------
// Read items from an OPC Group
//---------------------------------------------------------
OPCStat OPCReadGroupItems (int iGrp, struct Var_Stru v[] )
{
HRESULT r1;
HRESULT *hr;
OPCITEMSTATE *is;
int iItem;
OPCStat RetVal=OPCSuccess;
if (pGRPTagSIO[iGrp]) {
if (bOPCDebug) printf("Reading data .... \n");
r1 = pGRPTagSIO[iGrp]->Read(OPC_DS_CACHE,
OPCDataGroup[iGrp].iNumItems,
OPCDataGroup[iGrp].hItem,
&is,
&hr);
if (FAILED(r1)) {
printf("Error from Read(%lx)\n", r1);
RetVal = OPCError;
} else {
// if the read worked then copy results to the v structure based on type
for (iItem=0;iItem<OPCDataGroup[iGrp].iNumItems;iItem++ ) {
//printf("Read item= %d, hr= %lx, Quality= %2x", iItem, hr[iItem], is[iItem].wQuality);
if(!FAILED(hr[iItem])) {
// printf("%d", is[iItem].vDataValue.vt);
//printf("%d", iGrp);
switch(is[iItem].vDataValue.vt) {
case VT_I2: // 2
v[iItem].iVal = is[iItem].vDataValue.iVal;
break;
case VT_I4: // 3
v[iItem].lVal = is[iItem].vDataValue.lVal;
break;
case VT_R4: // 4
// printf("Z");
v[iItem].fVal = is[iItem].vDataValue.fltVal;
break;
case VT_R8: // 5
v[iItem].dblVal = is[iItem].vDataValue.dblVal;
break;
case VT_BOOL: // 11
v[iItem].bVal = is[iItem].vDataValue.boolVal;
break;
case VT_UI1: // 11
printf("TEST");
sprintf(v[iItem].cVal, "%s", is[iItem].vDataValue.cVal);
printf("%s", v[iItem].cVal);
printf("%c", v[iItem].cVal);
break;
case VT_BSTR: // 8
// printf("TEST");
sprintf(v[iItem].cVal,"%-.*ls", kOPCStringSize,is[iItem].vDataValue.bstrVal );
//printf("\n STRING STRING %s \n", v[iItem].cVal);
break;
default:
break;
}
}
if(iGrp >= 0 && iGrp <=)
{
stuct_double[iGrp-1][iItem] = v[iItem].dblVal;
// printf("group %d ", iGrp);
// printf("Tag %i: %10.2f\n", iItem, root_plc[iItem]);
}
if(iGrp > 0 && iGrp <= 44)
{
struc_floats[iGrp-1][iItem] = v[iItem].fVal;
//printf("GROUP %d ", iGrp);
//printf("Tag %i: %10.2f\n", iItem, struc_floats[iGrp-1][iItem]);
}
else
{
printf("Error reading data item %d\n", iItem);
//RetVal=OPCError; //Make not as severe -- rjf 06/03/02
RetVal=OPCWarning;
//break; //Escape the for-loop -- rjf- 5/13/02
}
*/
pIMalloc->Free(hr);
for (iItem=0;iItem<OPCDataGroup[iGrp].iNumItems;iItem)
{
VariantClear($is[iItem].vdatavalue)
}
pIMalloc->Free(is);
}
}
else{
RetVal=OPCError;
}
return (RetVal);
}
//-----------------------------------------
// Write items contained in an OPC Group
//-----------------------------------------
OPCStat OPCWriteGroupItems (int iGrp, struct Var_Stru vOut[] )
{
/* Data Access Method used in this sample */
const char* DAM = "Direct ODBC";
/* Connection string for Direct ODBC */
char szDSN[256] = "DSN=Gas_Meter_check;";
HRESULT r1,r2;
HRESULT *hr;
VARIANT v[nMaxOPCItems];
int iItem;
OPCStat RetVal=OPCSuccess;
if (pGRPTagSIO[iGrp]) {
for (iItem=0;iItem<OPCDataGroup[iGrp].iNumItems;iItem++) {
v[iItem].vt = OPCDataGroup[iGrp].iType;
switch(OPCDataGroup[iGrp].iType) {
case VT_I2: // 2
v[iItem].iVal = vOut[iItem].iVal;
break;
case VT_I4: // 3
v[iItem].lVal = vOut[iItem].lVal;
break;
case VT_R4: // 4
v[iItem].fltVal = vOut[iItem].fVal;
break;
case VT_R8: // 5
v[iItem].dblVal = vOut[iItem].dblVal;
HENV hEnv; HDBC hDbc;
/* ODBC API return status */ RETCODE rc;
int iConnStrLength2Ptr;
char szConnStrOut[256];
int i= 0;
char datetime[256];
double HMCO=1.0;
double HMR,HMT;
unsigned char* InsertQuery = "INSERT INTO Data ( [Date / Time], [Hot Strip Mill rate], [Hot Strip Mill Comm Okay], [Hot Strip Mill Total] ) SELECT #datetime# AS Expr1, HMR AS Expr2, 1 AS Expr3, HMCO AS Expr4, HMT AS Expr5;";
SQLCHAR chval1[128], chval2[128], colName[128];
int ret1;
int ret2;
/* Number of rows and columns in result set */
SQLINTEGER rowCount = 0;
SQLSMALLINT fieldCount = 0, currentField = 0;
HSTMT hStmt;
/* Allocate an environment handle */
rc = SQLAllocEnv(&hEnv);
/* Allocate a connection handle */
rc = SQLAllocConnect(hEnv, &hDbc);
/* Connect to the TakeCharge database */
rc = SQLDriverConnect(hDbc, NULL, (unsigned char*)szDSN,
SQL_NTS, (unsigned char*)szConnStrOut,
255, (SQLSMALLINT*)&iConnStrLength2Ptr, SQL_DRIVER_NOPROMPT);
if (SQL_SUCCEEDED(rc))
{
printf("%s: Successfully connected to database. Data source name: \n %s\n",
DAM, szConnStrOut);
/* Prepare SQL query */
printf("%s: SQL InsertQuery:\n %s\n", DAM, InsertQuery);
rc = SQLAllocStmt(hDbc,&hStmt);
rc = SQLPrepare(hStmt, InsertQuery, SQL_NTS);
/* Excecute the query and create a record set */
rc = SQLExecute(hStmt);
if (SQL_SUCCEEDED(rc))
{
printf("Executing query...");
printf("\n");
}
while (SQL_SUCCEEDED(rc))
{
printf(" insert passed\n");
rc = SQLFetch(hStmt);
rowCount++;
};
}
else
{
printf("%s: Couldn't connect to %s.\n", DAM, szDSN);
}
/* Disconnect*/
SQLDisconnect(hDbc);
printf("%s: Cleanup. Done.\n", DAM);
break;
case VT_BOOL: // 11
v[iItem].bVal = vOut[iItem].bVal;
break;
case VT_BSTR: // 8
// printf(" In Message value (VT_BSTR) = %s \n",vOut[iItem].cVal );
r2 = LPTSTR_to_BSTR ( &v[iItem].bstrVal , vOut[iItem].cVal);
if ( r2 != S_OK ) {
printf ("error in memory \n");
RetVal = OPCError;
}
// printf(" Write Msg value(VT_BSTR) = %ls \n", v[iItem].bstrVal );
report(0,0,0, "STRINGS data %s",vOut[iItem].cVal);
break;
default:
printf(" value(unknown type:%d) ", OPCDataGroup[iGrp].iType );
RetVal = OPCError;
break;
}
//if (bOPCDebug) DumpVariant(OPCDataGroup[iGrp].cTagNames[iItem], &v[iItem]);
}
r1 = pGRPTagSIO[iGrp]->Write(
OPCDataGroup[iGrp].iNumItems,
OPCDataGroup[iGrp].hItem,
v,
&hr);
if (FAILED(r1))
{
printf("Error from Write(%lx)\n", r1);
RetVal = OPCError;
} else {
//if (bOPCDebug) printf("Successful Write ... \n");
// Clear the Variant
for (iItem=0;iItem<OPCDataGroup[iGrp].iNumItems;iItem++) {
VariantClear(&v[iItem]);
}
pIMalloc->Free(hr);
}
} else {
RetVal = OPCError;
}
return(RetVal);
}
C/C++ is not my first language, and I am not familiar with your specific OPC library (there are so many), but according to my understanding of the code you are reading some kind of a variant variable, and with case statements you determine it's type and store it to proper property of v[iItem]. You repeat that in a loop for all tags in that group. There must be some property that tells you the name of the tag you have just read, and you can use it to solve the problem.
For example, if the current tag you are reading is of single float type, then this case section will be executed:
case VT_R4:
v[iItem].fVal = is[iItem].vDataValue.fltVal;
break;
So v[iItem].fVal contains the 4 bytes single float value of the OPC tag. If the current tag you are reading is of double float type, then this case section will be executed:
case VT_R8:
v[iItem].dblVal = is[iItem].vDataValue.dblVal;
break;
and v[iItem].dblVal contains the 8 bytes double float value of the OPC tag. I think you get the picture.
You should really spend some time with OPC DA tutorials on http://www.opcfoundation.org.

Resources