|
|
DLL to VB Communication
Last post 07-25-2006, 9:54 by jtrevatt. 18 replies.
-
-
06-08-2006, 13:38 |
-
wabbit
-
-

-
Joined on 10-28-2004
-
Perth, Western Australia
-
Posts 2,040
-
-
|
Re: DLL to VB Communication
Personally, I don't know, BUT I would be interested in the solution should you find one!
May I ask that you keep us informed on this one?
wabbit :D
"The question of whether a computer can think is no more interesting than the question of whether a submarine can swim." Edsgar W. Dijkstra MS: 6.52 EOD, 7.x EOD, 8.0 PRO, 9.2 PRO w/QC, 10 PRO w/QC C, 11 PRO w/QC & MDK For custom MetaStock programming : http://www.wabbit.com.au My SkyPE status :  My SkyPE account : wabbit.com.au
|
|
-
06-08-2006, 14:01 |
-
yachtfund
-
-
-
Joined on 05-22-2006
-
-
Posts 27
-
-
|
Re: DLL to VB Communication
Will do.
I began with looking at ths:-
http://www.codeproject.com/threads/interprocesscommunication.asp
And merged it with my very basic MSX DLL. I thought it was going to work but when I added an expert advisor errors started along the lines of 'access violation error' and I started drowning.
Im having a go at creating a VB Winsock app that listens to a port and the DLL sens info through it which is caught by the VB app.
Shall let yo know the outcome.
YachtFund
|
|
-
06-08-2006, 14:07 |
-
wabbit
-
-

-
Joined on 10-28-2004
-
Perth, Western Australia
-
Posts 2,040
-
-
|
Re: DLL to VB Communication
YF,
I had a whole series of access violation errors when I was trying to write some of my MSX functions. It turned out (I think??) that my <includes> were the cause. Try to use non .h headers where possible?? Particularly for the streams (istream, ostream ,iostream etc)
Worth a shot!
wabbit :D
"The question of whether a computer can think is no more interesting than the question of whether a submarine can swim." Edsgar W. Dijkstra MS: 6.52 EOD, 7.x EOD, 8.0 PRO, 9.2 PRO w/QC, 10 PRO w/QC C, 11 PRO w/QC & MDK For custom MetaStock programming : http://www.wabbit.com.au My SkyPE status :  My SkyPE account : wabbit.com.au
|
|
-
06-08-2006, 14:13 |
-
yachtfund
-
-
-
Joined on 05-22-2006
-
-
Posts 27
-
-
|
Re: DLL to VB Communication
wabbit
I currently have all these:-
#include "stdafx.h"
#include "winuser.h"
#include "comutil.h"
#include <string.h>
#include <float.h>
#include <math.h>
#include <stdlib.h>
#include "MSXStruc.h"
Some start with < some ", dont know the difference...
YF
|
|
-
06-08-2006, 14:16 |
-
wabbit
-
-

-
Joined on 10-28-2004
-
Perth, Western Australia
-
Posts 2,040
-
-
|
Re: DLL to VB Communication
Not having used winuser.h and comutil.h I couldnt say for sure if they are the problem?
Is there a non .h version? An MFC version?
"The question of whether a computer can think is no more interesting than the question of whether a submarine can swim." Edsgar W. Dijkstra MS: 6.52 EOD, 7.x EOD, 8.0 PRO, 9.2 PRO w/QC, 10 PRO w/QC C, 11 PRO w/QC & MDK For custom MetaStock programming : http://www.wabbit.com.au My SkyPE status :  My SkyPE account : wabbit.com.au
|
|
-
06-08-2006, 14:21 |
-
yachtfund
-
-
-
Joined on 05-22-2006
-
-
Posts 27
-
-
|
Re: DLL to VB Communication
I dont know C++ that well so no idea.
|
|
-
06-08-2006, 14:26 |
-
wabbit
-
-

-
Joined on 10-28-2004
-
Perth, Western Australia
-
Posts 2,040
-
-
|
Re: DLL to VB Communication
neither do I!
"The question of whether a computer can think is no more interesting than the question of whether a submarine can swim." Edsgar W. Dijkstra MS: 6.52 EOD, 7.x EOD, 8.0 PRO, 9.2 PRO w/QC, 10 PRO w/QC C, 11 PRO w/QC & MDK For custom MetaStock programming : http://www.wabbit.com.au My SkyPE status :  My SkyPE account : wabbit.com.au
|
|
-
06-08-2006, 14:45 |
-
Branden Russell
-
-

-
Joined on 11-28-2005
-
Salt Lake City, UT
-
Posts 269
-
-
|
yachtfund: ...
Some start with < some ", dont know the difference...
YF
<> go around headers that are built in, headers that are found in the main directory. The compiler will already know where those are.
"" go around headers that are custom and need to be added into the solution or include a path of where to get to them.
Equis International, Inc. A Thomson Reuters Company 90 S. 400 W Suite 620 SLC, UT 84101
|
|
-
-
06-08-2006, 15:41 |
-
06-08-2006, 16:19 |
-
yachtfund
-
-
-
Joined on 05-22-2006
-
-
Posts 27
-
-
|
Im still getting the access violation problem. Im going to try using Winsock to pass my info but just incase anyone wants to have a look at the code and see if there is anything glaringly obvious:-
Code:
//Inter Process Communication Example, Visual C++ 6.0 Test DLL
//Programming by Axonn Echysttas. E-Mail: axonnus at yahoo dot com
//Comment Language: English.
//
//Main DLL source file.
//Created on 2005-07-10. Last updated on 2005-11-04.
//For the creation of this code, I would like to express my thanks to:
//Nicholas Skapura from flipcode.com, moeur from vbforums.com, Randor from www.codeproject.com
//and all the people-that-help-people on the CodeProject Message Boards or other Forums,
//especially to those which personally helped me by answering my questions.
#include "stdafx.h"
#include <winuser.h> //API functions.
#include <comutil.h> //For the _variant_t data type.
#include <string.h>
#include <float.h>
#include <math.h>
#include <stdlib.h>
// TODO: Make sure this include is in your search path or added explicitly to the project.
#include "MSXStruc.h" // required definitions
// we don't want C++ name-mangling
#ifdef __cplusplus
extern "C" {
#endif
#pragma bss_seg("DLLShare") //Sharing uninitialized data across instances of the DLL.
HWND hwndExternalApplication; //Handle to the VB Test Application.
//Addresses of public procedures declared in the module of the VB Test
//Application and which can be called by the VC++ DLL from the EXE of the
long extNumberProc; //VB Test Application. These will be called throughout the
long extStringProc; //DLL. The addresses are received from the VB Application as long
long extStructureProc; //parameters upon the call of the Activate procedure.
long extArrayProc;
#pragma bss_seg()
//A structure used to transmit various information to the VB Test Application.
struct DLLStatusStruct
{
long lFirst;
long lSecond;
long lThird;
long lFourth;
long lFifth;
long lSixth;
};
//A structure with more diverse members.
struct AdvancedStruct
{
long lFirst;
long lSecond;
_variant_t sThird; //The _variant_t type is a COM type used to send strings back to VB.
BSTR sFourth; //But BSTR can also be used.
};
HANDLE hDLL; //Instance handle of this DLL.
//The entry point for the DLL.
BOOL APIENTRY DllMain (HANDLE hModule, DWORD ul_reason_for_call, LPVOID lpReserved)
{
hDLL = hModule;
BOOL l_bRtrn = TRUE;
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH: //When a process connects to the DLL, displaying a debug message.
SendMessage(hwndExternalApplication, WM_SETTEXT, NULL, (LPARAM) "Process attached to VC++ TEST DLL. (Sent via WM_SETTEXT)");
break;
case DLL_THREAD_ATTACH:
break;
case DLL_THREAD_DETACH:
break;
case DLL_PROCESS_DETACH: //When a process disconnects from the DLL, displaying a debug message.
SendMessage(hwndExternalApplication, WM_SETTEXT, NULL, (LPARAM) "Process dettached from VC++ TEST DLL. (Sent via WM_SETTEXT)");
break;
}
return TRUE;
}
///////////////////////////////////////////////////////////////////////////////
//FUNCTIONS USED INTERNALLY BY THE DLL
///////////////////////////////////////////////////////////////////////////////
//Converts a Char to a BSTR. Needed when working with strings with Visual Basic.
BSTR ConvertCharToBSTR(char* CharValue)
{
int i; //Iteration counter.
int iLength = strlen(CharValue); //Finding out the length of the Char.
unsigned short* bstrResult = new unsigned short[iLength + 1]; //Creating a BSTR with the required length.
//Going through the Char characters.
for (i = 0; i < iLength; i++)
{
char iCharacter = CharValue[i]; //Taking the next char.
bstrResult[i] = iCharacter; //Adding it to the string.
bstrResult[i + 1] = '\\0'; //Adding the null-termination.
}
return bstrResult; //Returning the result.
}
///////////////////////////////////////////////////////////////////////////////
//FUNCTIONS THAT CALL OTHER FUNCTIONS FROM THE VISUAL BASIC TEST APPLICATION
//(VISUAL C++ -> VISUAL BASIC)
///////////////////////////////////////////////////////////////////////////////
//Using the extNumberProc variable, which is a pointer to the VB function for Numbers, calling
//that function and passing to it the value received as parameter.
void CallVBFunctionForNumber (long lSomeValueToSend)
{
typedef long (__stdcall *OutsideFunction)(long AValue); //Defining the prototype of the function.
OutsideFunction FunctionCall; //Creating an instance that will be used to call the function.
FunctionCall = (OutsideFunction)extNumberProc; //Assigning the address to be used for the call.
long da = FunctionCall(lSomeValueToSend); //Calling the function with the parameter.
da++;
}
//Using the extStringProc variable, which is a pointer to the VB function for Strings,
//calling that function and passing to it the value received as parameter.
void CallVBFunctionForString (char *cSomeStringToSend)
{
typedef void (__stdcall *OutsideFunction)(BSTR AValue); //Same as above, creating a function
OutsideFunction FunctionCall; //prototype, instantiating it, and linking it to the real VB
FunctionCall = (OutsideFunction)extStringProc; //function by doing this cast.
BSTR bstrTemp = ConvertCharToBSTR(cSomeStringToSend); //VB Strings need a BSTR parameter.
//Now that we have a BSTR, using SysAllocString on it and calling the VB function.
FunctionCall(SysAllocString(bstrTemp));
}
//Using the extStructureProc variable, which is a pointer to the VB function for
//Structures, calling that function and passing to it a structure created locally.
void CallVBFunctionForStructure ()
{
typedef void (__stdcall *OutsideFunction)(AdvancedStruct *AValue); //Same as above, creating a function
OutsideFunction FunctionCall; //prototype, instantiating it, and linking it to the real VB
FunctionCall = (OutsideFunction)extStructureProc; //function by doing this cast.
AdvancedStruct *cmForCall = new AdvancedStruct; //Creating a new structure.
cmForCall->lFirst = 10; //Setting its members.
cmForCall->lSecond = 33;
cmForCall->sThird = (_variant_t)"Some string value hardcoded in VC++.";
FunctionCall(cmForCall); //Calling the VB function.
delete cmForCall; //Freeing the memory.
}
//Using the extArrayProc variable, which is a pointer to the VB function for Arrays, calling
//that function and passing to it a locally created array of numbers and then strings.
void CallVBFunctionForArray ()
{
typedef void (__stdcall *OutsideFunction)(VARIANT *AValue); //Same as above, creating a function
OutsideFunction FunctionCall; //prototype, instantiating it, and linking it to the real VB
FunctionCall = (OutsideFunction)extArrayProc; //function by doing this cast.
VARIANT pVariant; //A variant typed pointer.
SAFEARRAY *sarrVC; //The safe array.
SAFEARRAYBOUND sabBound; //For the array properties (elements and bounds).
sabBound.cElements = 10; sabBound.lLbound = 0; //Setting number of elements and bounds.
VariantInit (&pVariant); //Initializing.
//NUMERIC ARRAY.
pVariant.vt = VT_ARRAY | VT_I4; //Setting the type of the variant.
sarrVC = SafeArrayCreate(VT_I4, 1, &sabBound); //Creating the safe array.
for (long lCounter = 0; lCounter < 10; lCounter++) //Inserting data in the array.
{ long lToSend = lCounter * lCounter; SafeArrayPutElement(sarrVC, &lCounter, &lToSend); }
pVariant.parray = sarrVC; //Setting the data of the Variant.
FunctionCall(&pVariant); //Calling the VB function.
SafeArrayDestroy(sarrVC); //Freeing memory.
//STRING ARRAY.
BSTR sarrToSend[5]; //A BSTR string array (VB uses BSTR. It might be possible to use another type).
sabBound.cElements = 5; //This array will only have 5 elements.
sarrToSend[0] = SysAllocString(ConvertCharToBSTR("1st value")); //Populating the BSTR array.
sarrToSend[1] = SysAllocString(ConvertCharToBSTR("The 2 value"));
sarrToSend[2] = SysAllocString(ConvertCharToBSTR("III value"));
sarrToSend[3] = SysAllocString(ConvertCharToBSTR("Value number 4"));
sarrToSend[4] = SysAllocString(ConvertCharToBSTR("Fifth and last value"));
pVariant.vt = VT_ARRAY | VT_BSTR; //Setting the type of the variant.
sarrVC = SafeArrayCreate(VT_BSTR, 1, &sabBound); //Creating the safe array.
for (lCounter = 0; lCounter < 5; lCounter++) //Inserting data in the array.
{ SafeArrayPutElement(sarrVC, &lCounter, sarrToSend[lCounter]); }
pVariant.parray = sarrVC; //Setting the data of the Variant.
FunctionCall(&pVariant); //Calling the VB function.
SafeArrayDestroy(sarrVC); //Freeing memory.
for (lCounter = 0; lCounter < 5; lCounter++) //Also freeing memory used by the BSTR string array.
SysFreeString(sarrToSend[lCounter]);
}
//////////////////////////////////////////////////////////////////////////////
//FUNCTIONS CALLED FROM THE VISUAL BASIC TEST APPLICATION
//(VISUAL BASIC -> VISUAL C++)
//////////////////////////////////////////////////////////////////////////////
//Intializes the DLL.
void WINAPI Activate (long lVBNumberDemoFunction, long lVBStringDemoFunction, long lVBStructureDemoFunction, long VBArrayDemoFunction)
{
hwndExternalApplication = FindWindow(NULL, "Test VB Application"); //Getting the handle for the Visual Basic Test Application.
//Saving the data received from the VB Test Application in the global variables of the DLL.
extNumberProc = lVBNumberDemoFunction; //These long parameters will hold the addresses of
extStringProc = lVBStringDemoFunction; //public functions from the VB Test Application and will
extStructureProc = lVBStructureDemoFunction; //be used to call these functions throughout the DLL.
extArrayProc = VBArrayDemoFunction;
//Sending a message to the VB Application. The VB Application is subclassed and trained
//to handle these messages. See there for details, in the Functionality.bas module.
SendMessage(hwndExternalApplication, WM_SETTEXT, NULL, (LPARAM) "Addresses of VB functions saved. Ready for demonstration. (Sent via WM_SETTEXT)");
SendMessage(hwndExternalApplication, WM_USER + 241, NULL, (LPARAM) "Addresses of VB functions saved. Ready for demonstration. (Sent via WM_USER + 241)");
}
//The VB Application will call this function to trigger the DLL to begin a particular demonstration.
void WINAPI Demonstrate (int WhatToDemonstrate)
{
switch (WhatToDemonstrate) //Depending on what demonstration has been commanded.
{
case 1: //Demo 1 = Demonstrate calling a string function from VB.
{
CallVBFunctionForString("Greetings from VC++!"); //Calling a VB function that accepts a string as parameter.
break;
}
case 2: //Demo 2 = Demonstrate calling a number function from VB.
{
CallVBFunctionForNumber(22); //Calling a VB function that accepts a (long) number as parameter.
break;
}
case 3: //Demo 3 = Demonstrate calling a structure function from VB.
{
CallVBFunctionForStructure(); //Calling the VB function for structures.
break;
}
case 4: //Demo 4 = Demonstrate sending data via WM_COPYDATA.
{
COPYDATASTRUCT cdsData; //The structure used to send data.
//SENDING A STRING VIA WM_COPYDATA.
char cTemp[50]; //A temporary character.
BSTR sString; //String to send to VB.
strcpy(cTemp, "This is the string passed via WM_COPYDATA.\\0"); //The string to send.
sString = SysAllocString(ConvertCharToBSTR(cTemp)); //Creating VB compatible string.
cdsData.dwData = 1000; //Setting an arbitrary value which will tell VB we're sending a string.
cdsData.cbData = strlen(cTemp)*2; //Wide characters = lenght times two.
cdsData.lpData = sString; //Setting the string to be sent.
//Sending the data.
SendMessage(hwndExternalApplication, WM_COPYDATA, (WPARAM)hwndExternalApplication, (LPARAM)&cdsData);
SysFreeString(sString); //Freeing memory used by SysAlloc.
//SENDING AN ARRAY OF LONGS VIA WM_COPYDATA.
long larrNumbers[5] = {4, 6, 0, 1, 8}; //The array to be sent.
cdsData.dwData = 1001; //Indicating VB we're sending a long array.
cdsData.cbData = 5 * sizeof(long); //Lenght of the array times the size of the long data type.
cdsData.lpData = larrNumbers; //Setting the data to be sent.
//Sending the data.
SendMessage(hwndExternalApplication, WM_COPYDATA, (WPARAM)hwndExternalApplication, (LPARAM)&cdsData);
//MY METHOD OF SENDING AN ARRAY OF STRINGS TO VB (there are several others possible
//but I consider this one has a higher educational value).
int iStrings = 5; //Number of strings to be sent.
char cArrayTemp[5][50]; //The array of strings.
BSTR sSendString; //String to send in a step.
strcpy(cArrayTemp[0], "The first string.");
strcpy(cArrayTemp[1], "Second string.");
strcpy(cArrayTemp[2], "T H I R D.");
strcpy(cArrayTemp[3], "Fourth");
strcpy(cArrayTemp[4], ""); //When encountering this element VB will know the array ended.
//Signalling the end of the array could also be done by sending some WM_USER + SOMETHING
//message to the VB application or sending a special string token.
for (int iCounter = 0; iCounter < 5; iCounter ++) //Sending the array in steps.
{ //Allocating space for this particular element of the array.
sSendString = SysAllocString(ConvertCharToBSTR(cArrayTemp[iCounter]));
cdsData.dwData = 1002 + iCounter; //Telling VB that we're sending a string array.
//Also adding the iCounter to the value to tell VB which element this is.
cdsData.cbData = strlen(cArrayTemp[iCounter])*2; //Wide characters = lenght times two.
cdsData.lpData = sSendString; //Setting the string to be sent.
//Sending the data.
SendMessage(hwndExternalApplication, WM_COPYDATA, (WPARAM)hwndExternalApplication, (LPARAM)&cdsData);
SysFreeString(sSendString); //Freeing memory used by SysAlloc.
}
break;
}
case 5: //Demo 5 = Demonstrate calling a VB function with an array parameter.
{
CallVBFunctionForArray();
break;
}
}
}
//The VB Application will call this function passing it a LONG parameter. This function will
//notify that it successfully received the value, by calling another function, from the VB
//and passing it a string value. See the StringDemoFunction's comments, in the VB Application.
void WINAPI VCNumber (long ValueFromVB)
{
char cValue[12]; //Used to convert the value received from VB.
char cText[30] = "The number is: "; //The final result.
_ltoa(ValueFromVB, cValue, 10); //Converting the value from VB to a text.
strcat(cText, cValue); //Adding the text after the "The number is: " text.
CallVBFunctionForString(cText); //Sending the text obtained above back to the VB Application.
}
//This function will return a structure back to the VB Application. The VB Application calls
//this function and specifies a Number argument and a Text argument.
AdvancedStruct WINAPI VCStructure (long Number, BSTR Text)
{
AdvancedStruct cmResponse; //Used to fill out the members of the structure.
char cTemp[2000]; //Used for concatenation.
strcpy(cTemp, (LPCSTR)Text); //First, adding in cTemp the value from VB.
strcat(cTemp, " Concatenated with this string from VC++."); //Now adding some more text to it.
cmResponse.lFirst = Number; //Sending back the number.
cmResponse.lSecond = Number + 200; //The number plus a value.
cmResponse.sThird = _variant_t(cTemp); //And finally, the concatenated text from above, as _variant_t.
//_variant_t must be used for a good transmission of strings from VC++ to VB (COM).
cmResponse.sFourth = SysAllocString((LPCWSTR)"This is a BSTR String in VC++."); //Sending via BSTR casted to LPCWSTR.
return cmResponse;
}
//Returns data about the DLL. Uses *Response, a parameter received through reference to send back data to Visual Basic.
void WINAPI GetDLLData (DLLStatusStruct *Response)
{
Response->lFirst = extNumberProc; //Sending back to the Visual Basic application the addresses of its own functions.
Response->lSecond = extStringProc; //These addresses were set above, in the Activate procedure. When calling this
Response->lThird = extStructureProc; //function from Visual Basic, the DLLStatusStruct variable received as parameter
Response->lFourth = extArrayProc; //will be filled with data and Visual Basic will read and display that data.
Response->lFifth = 123; //As the fifth value, returning a hardcoded value.
Response->lSixth = GetTickCount(); //As the sixth value, returning the result of the GetTickCount function.
}
//Receives from VB a numeric array and returns the element designated by the Index.
long WINAPI VCNumericArray (LPSAFEARRAY FAR *ArrayData, int Index)
{
long *sarrTemp; //Array used to put the argument in.
sarrTemp = (long*)(*ArrayData)->pvData; //Taking the array into our local one.
Index--; //Decreasing Index with 1 since in VB arrays begin with 1, not 0.
sarrTemp[1] += 100; //Modifying the second element of the array.
return(sarrTemp[Index]); //Returning the requested value.
}
//Receives from VB a string array and returns the element designated by the Index.
BSTR WINAPI VCStringArray (LPSAFEARRAY FAR *ArrayData, int Index)
{
BSTR *sarrTemp; //Array used to put the argument in.
sarrTemp = (BSTR*)(*ArrayData)->pvData; //Taking the array into our local one.
Index--; //Decreasing Index with 1 since in VB arrays begin with 1, not 0.
return(SysAllocString(sarrTemp[Index])); //Returning the requested value.
}
BOOL __stdcall MSXInfo (MSXDLLDef *a_psDLLDef)
{
// TODO: replace with your copyright information...
strncpy (a_psDLLDef->szCopyright, "Copyright (c) ",
sizeof(a_psDLLDef->szCopyright)-1);
// TODO: set the number of functions you are exporting
// (don't forget to add them to your .def file)
a_psDLLDef->iNFuncs = 1; // change this if you have more than 1 function to export.
a_psDLLDef->iVersion = MSX_VERSION;
return MSX_SUCCESS;
}
BOOL __stdcall MSXNthFunction (int a_iNthFunc, MSXFuncDef *a_psFuncDef)
{
int l_bRtrn = MSX_SUCCESS; // no error
switch (a_iNthFunc)
{
// TODO: define a case entry (starting at 0) for each of your functions
// This "EmptyFunc" entry should be modified with the name and description
// of your function.
case 0:
strcpy (a_psFuncDef->szFunctionName, "NewAlert");
strcpy (a_psFuncDef->szFunctionDescription, "Metastock has a new strategy alert.");
a_psFuncDef->iNArguments = 1;
break;
default:
l_bRtrn = MSX_ERROR; // This will help MSXTest find errors in your code
break;
}
return l_bRtrn;
}
BOOL __stdcall MSXNthArg (int a_iNthFunc, int a_iNthArg,
MSXFuncArgDef *a_psFuncArgDef)
{
BOOL l_bRtrn = MSX_SUCCESS;
a_psFuncArgDef->iNCustomStrings = 0; // init just to be nice
// If your functions have arguments, uncomment this switch statement
// and add the appropriate case statements.
switch (a_iNthFunc) {
case 0: // NewAlert
switch (a_iNthArg) {
case 0: // NewAlert:Arg0
a_psFuncArgDef->iArgType = MSXString; // String
strcpy (a_psFuncArgDef->szArgName, "AlertType");
break;
default:
l_bRtrn = MSX_ERROR; // This will help MSXTest find errors in your code
break;
}
break;
default:
l_bRtrn = MSX_ERROR; // This will help MSXTest find errors in your code
break;
}
return l_bRtrn;
}
#define MSXMax(a,b) (((a) > (b)) ? (a) : (b))
#define MSXMin(a,b) (((a) < (b)) ? (a) : (b))
double ForceFloatRange (double a_lfDbl)
{
if (a_lfDbl > 0.0)
{
a_lfDbl = MSXMin (a_lfDbl, double(FLT_MAX)); // make sure pos number <= FLT_MAX
a_lfDbl = MSXMax (a_lfDbl, double(FLT_MIN)); // make sure pos number >= FLT_MIN
}
else
{
if (a_lfDbl < 0.0)
{
a_lfDbl = MSXMax (a_lfDbl, double(-FLT_MAX)); // make sure neg number >= -FLT_MAX
a_lfDbl = MSXMin (a_lfDbl, double(-FLT_MIN)); // make sure neg number <= -FLT_MIN
}
}
return a_lfDbl;
}
BOOL __stdcall NewAlert (const MSXDataRec *a_psDataRec,
const MSXDataInfoRecArgsArray *a_psDataInfoArgs,
const MSXNumericArgsArray *a_psNumericArgs,
const MSXStringArgsArray *a_psStringArgs,
const MSXCustomArgsArray *a_psCustomArgs,
MSXResultRec *a_psResultRec)
{
BOOL l_bRtrn = MSX_SUCCESS;
CallVBFunctionForString("Adams Here");
// in case you don't flesh this out before running it, we'll invalidate
// the return array to prevent potential problems.
a_psResultRec->psResultArray->iFirstValid = 0;
a_psResultRec->psResultArray->iLastValid = -1;
return l_bRtrn;
}
#ifdef __cplusplus
}
#endif
|
|
-
06-15-2006, 22:43 |
-
jtrevatt
-
-
-
Joined on 05-25-2006
-
Brisbane, Australia
-
Posts 13
-
-
|
RE: DLL to VB Communication
Hi YachtFund,
I have a similiar goal as you do - sending my trading signals to an external VB app. I considered a number of ways to achieve the communication process including writing to text files, using winsock, using DDE and finally (the one I am happy with) writing to a SQL database table. I decided this simply because it involves the least amount of code. I also considered that I would want to record all my 'filtered' signals in a database anyway for easy access, so it seemed more logical to put it straight in there than through winsock and then into a database. I have a VB.NET app which then accepts calls from the database events (SQL Server 2005) so that I can process the signals using my 'Trading Rules Engine'. To me it makes a lot more sense implementing the business rules for the trades outside of Metastock and the MSX DLL. This approach gives you the most flexibility in being able to change your rules and use your signals any which way you want. Be it to put into an automated trading system (such as my goal) or to email/sms traders.
Jeremy
|
|
-
06-17-2006, 12:46 |
-
yachtfund
-
-
-
Joined on 05-22-2006
-
-
Posts 27
-
-
|
Re: RE: DLL to VB Communication
Hi Jeremy
Looking forward to getting this done so I can play more golf!! Did you manage to get the Winsock code working?
Cheers
YF
|
|
-
-
07-24-2006, 14:49 |
-
yachtfund
-
-
-
Joined on 05-22-2006
-
-
Posts 27
-
-
|
Re: DLL to VB Communication
Hi jtrevatt
I can write to a file, which is easy and thats one way I could do it.
Im having problems connecting to my vb winsock server though, good article here http://www.planet-source-code.com/vb/scripts/ShowCode.asp?txtCodeId=2241&lngWId=3 although i cant get it working.
Do you fancy putting up the basic code that you have to connect to the server?
My none working one so far is below, Im getting 'Failed to establish connection with server.'
Why oh why oh why oh why, I ask you.
BOOL __stdcall NewAlert (const MSXDataRec *a_psDataRec,
const MSXDataInfoRecArgsArray *a_psDataInfoArgs,
const MSXNumericArgsArray *a_psNumericArgs,
const MSXStringArgsArray *a_psStringArgs,
const MSXCustomArgsArray *a_psCustomArgs,
MSXResultRec *a_psResultRec)
{
// open log file
ofstream myfile;
myfile.open ("log.txt", ios::app);
// myfile << "Writing this to a file.\\n";
// initialise
WSADATA WsaDat;
int winsockInitialise = WSAStartup(MAKEWORD(1, 1), &WsaDat);
// if the initialisation was succesful
if(winsockInitialise == 0){
// create a sockeet
SOCKET Socket;
Socket = socket(AF_INET, SOCK_STREAM, 0);
// if creating the socket was succesful
if (Socket != INVALID_SOCKET){
myfile << "Not INVALID_SOCKET.\\n";
SOCKADDR_IN SockAddr;
SockAddr.sin_port = 1007;
SockAddr.sin_family = AF_INET;
SockAddr.sin_addr.S_un.S_un_b.s_b1 = 192;
SockAddr.sin_addr.S_un.S_un_b.s_b2 = 168;
SockAddr.sin_addr.S_un.S_un_b.s_b3 = 1;
SockAddr.sin_addr.S_un.S_un_b.s_b4 = 3;
// check socet connection
if (connect(Socket, (SOCKADDR *)(&SockAddr), sizeof(SockAddr)) != 0)
{
// if no connection
myfile << "Failed to establish connection with server.\\n";
}else{
// log a connection
myfile << "Establish connection with server.\\n";
/*
int RetVal = SOCKET_ERROR;
char String[] = "Hello";
while (RetVal == SOCKET_ERROR)
{
RetVal = recv(Socket, String, strlen(String) + 1, 0);
if ((RetVal == 0)||(RetVal == 1)||(RetVal == 2))
{
myfile << "Connection closed at other end.\\n";
break;
}
}
*/
}
}else{
// socket not initialised
myfile << "INVALID_SOCKET.\\n";
}
}
BOOL l_bRtrn = MSX_SUCCESS;
// in case you don't flesh this out before running it, we'll invalidate
// the return array to prevent potential problems.
a_psResultRec->psResultArray->iFirstValid = 0;
a_psResultRec->psResultArray->iLastValid = -1;
// close file
myfile.close();
return l_bRtrn;
}
|
|
-
07-24-2006, 21:53 |
-
jtrevatt
-
-
-
Joined on 05-25-2006
-
Brisbane, Australia
-
Posts 13
-
-
|
TCP client connection code
Hi Yachtfund,
My client code is quite simple (pasted below). All of the hard stuff is actually built into PowerBASIC already, so sending something involves a basic call to the built-in functions. Therefore I dont think this code will illumunate you much.
I assume that since you have a VB Winsock server running you have also tested it out using a VB Winsock Client? At least to prove that you are not missing something really basic. Its frustrating how many times I have looked for hours for complex solutions when the really simple answer was slapping me in the face the whole time!
One of the problems I had to overcome was just unblocking the port/app in the firewall software (in my case just the built-in windows firewall. But I know that AVG and Nortons treat blocking in different ways.
Also, in my situation I wanted to develop and test locally (on my notebook computer) and then move it into a true production environment that has multiple client machines. Under XP, when you are testing both client and server on the same machine, it is easier to have the server and client listening on different ports. Therefore I set up both the server and client apps to communicate on 2 ports. An upstream (outbound) port and a downstream (inbound) port. So, for example, the client listens on port 997 and sends on port 998, while the server listens on port 998 and sends on port 997. Therefore it is easy to get it working in dev and of course will also work in a multiple machine environment as well. For the same reason its also a good idea to make sure that you are using ports that arent likely to be used by other applications.
Seeing as your error message was not exactly specific (typical I know) I am blatting you with possible solutions. I think though that the most important thing would be to try and get a sample piece of code (such as the vb winsock ones) working (client and server) on the same machine. Then you have at least proved that the basics are working on the ports you have chosen. You might have already done all this... in which case Ive been rambling for no good reason :)
LOCAL nSocket AS LONG
LOCAL sBuffer AS STRING
LOCAL sPacket AS STRING
LOCAL l_bRtrn AS LONG
TCP OPEN PORT 999 AT "127.0.0.1" AS nSocket TIMEOUT 5000
IF ERR THEN
'MSGBOX "Error opening port: " + STR$(ERR)
EXIT SUB
END IF
IF LEN(COMMAND$) THEN
TCP PRINT nSocket, COMMAND$;
ELSE
TCP PRINT nSocket, sMessage;
END IF
TCP CLOSE nSocket
|
|
-
07-25-2006, 9:19 |
-
yachtfund
-
-
-
Joined on 05-22-2006
-
-
Posts 27
-
-
|
Re: TCP client connection code
Ramble away jtrevatt!!
I have got the VB server/client working. You might be right about the firewalls. I have tried turning them off but you cant tell with these pesky Windows systems, they never do what you tell them to do.
I shall plug away.
Have you manged to get your full auto system working yet? Are you going to trust it to its own devices for long amounts of time or are you going to watch it faily closely? Im hoping mine can be left so I can play with my train set.
YF
|
|
-
|
|