|
Thankyou. You have helped me immensely. It almost works now; I can run my test exe from C++, now "just" need to get the real thing running.
If I discover anything new I will report it. Meanwhile I am very grateful.
-------------
Bibo ergo sum
|
|
|
|
|
Another possible difference to running it from the command line is the location of the working directory (I note that you seem to be using filenames and not full paths). Maybe you are now successfully transferring the filenames but the working directory is different, perhaps somewhere where the program doesn't have permission, or a file that should exist in it doesn't.
The statement:
OPEN(17,FILE=FILEN,FORM='FORMATTED',STATUS='OLD',
$ READONLY,IOSTAT=IOS)
will give you some sort of error if the file doesn't exist as STATUS='OLD' tells the program that it should be there.
Peter
"Until the invention of the computer, the machine gun was the device that enabled humans to make the most mistakes in the smallest amount of time."
|
|
|
|
|
Yes yes yes!
I put the whole path in (without doubling the \) and the test program works. It doesn't work for the original Fortran yet but at least I know where to start. If Fortran is only going to give it 80 chars every time I can see some problems coming up on the target machine, because the paths can get a lot longer. I did try a relative path but it wasn't having it, must try and get Fortran to tell me where it is. In C++ I use _getcwd, can someone tell me how to get it in Fortran?
It was giving me IOS=2, which is not in the list of Intel error messages.
-------------
Bibo ergo sum
|
|
|
|
|
To find out where you are, GNU Fortran has a GETCWD call
link[^] I don't know how standard it is.
It doesn't seem to have a corresponding SETCWD call.
If you are starting the program using CreateProcess() then you can set the working directory, and I think it will default to the working directory of the calling process if you don't.
Peter
"Until the invention of the computer, the machine gun was the device that enabled humans to make the most mistakes in the smallest amount of time."
|
|
|
|
|
Unfortunately the Absoft compiler is a bit basic and does not have such luxuries. But I must check what I put in CreateProcess. I have to put it all in the command line, maybe I missed the path and it was just luck that it ran where it is.
-------------
Bibo ergo sum
|
|
|
|
|
Check out the lpCurrentDirectory parameter to the CreateProcess call
Peter
"Until the invention of the computer, the machine gun was the device that enabled humans to make the most mistakes in the smallest amount of time."
|
|
|
|
|
Hi,
if pathname length is a concern, you can always "map a network drive" (it works on the local machine too, despite the name), i.e. assign a drive letter to a (deep) subdirectory, allowing you to shorten the pathname considerably.
|
|
|
|
|
Fixed it!
I finally ported the old Fortran to Windows and recompiled it. I put some prints in to see what it gets up to.
It works. The problem was the Fortran having been compiled under Cygwin, some kind of Linux for Windows. It ran under Windows, but not quite. So when I compiled it myself, it could use the strings to open the file.
Just because it runs from the command line does not mean you can embed it and it still runs.
|
|
|
|
|
Hello
I have a MFC program with 2 threads. First is User Interface (Main) thread, and second one is worker thread that is created in the beginning and used till the end of application life. In the second thread in the begining I create CInternetSession and CHTTPConnection. I make some HTTP requests from second thread and everything is fine. But this is until I create and show InternetExplorer control in UserInterfece thread. Then something goes wrong and i lost my cookies in second thread and after a few requests my application crash (I will find where in code exactly this happened) When I show Internet Explorer control my second thread didn't make are requests. But I think that the problem is related with multithread using of WinInet libraries.
I found this problem soon because it didn't happened on computers that have all windows updates (Windows XP)
What you will recommend me to do?
P.S. I forget to mention that in second thread I make mostly a HTTPS requests
P.S. IE Control that I use is this one
http://www.codeproject.com/KB/miscctrl/simplebrowserformfc.aspx[^]
Julian Popov
абвгдежзийклмнопрстуфхцчшщъьюя
modified on Tuesday, December 9, 2008 6:04 AM
|
|
|
|
|
For one of my projects I've created a class wrapper around some functions contained in a DLL. To use these DLL functions, I instantiate an object of the type class wrapper, and then call the member function LoadDLL(). LoadDLL() calls ::LoadLibrary() for the DLL, and then calls GetProcAddress() for each DLL function I wish to wrap. If any of the functions couldn't be found, I wish to FreeLibrary(), and return false.
At the moment I do something along the lines of:
typedef void (*p2DLLFunc1) (void);
typedef char* (*p2DLLFunc2) (void);
bool CDLLWrapper::LoadDLL()
{
bool bResult = false;
m_hmoduleDll = ::LoadLibrary(_T("DLLName"));
if (NULL != m_hmoduleDll)
{
m_funcDLLFunc1 = reinterpret_cast<p2DLLFunc1>(GetProcAddress(m_hmoduleDll, _T("DLLFunc1")));
m_funcDLLFunc2 = reinterpret_cast<p2DLLFunc2>(GetProcAddress(m_hmoduleDll, _T("DLLFunc2")));
m_funcDLLFunc3 = reinterpret_cast<p2DLLFunc1>(GetProcAddress(m_hmoduleDll, _T("DLLFunc3")));
if ( NULL != m_funcDLLFunc1 &&
NULL != m_funcDLLFunc2 &&
NULL != m_funcDLLFunc3)
{
bResult = true;
}
else
{
::FreeLibrary(m_hmoduleDll);
}
}
return bResult;
}
However, when lots of functions are being wrapped the above method is a bit tedious and can be error prone. Instead, I would like to do it with a lookup table, like so
bool CDLLWrapper::LoadDLL()
{
struct MyLUT {
TCHAR* tcFuncName;
funcDLLFunc;
int iFunctionSignatureType;
};
static MyLUT arrWrappedFuncs[] = { _T("DLLFunc1"), m_funcDLLFunc1, 0
_T("DLLFunc2"), m_funcDLLFunc2, 1
_T("DLLFunc3"), m_funcDLLFunc3, 0
};
const int iNUM_WRAPPED_FUNCTIONS = sizeof(arrWrappedFuncs) / sizeof(MyLUT);
bool bResult = false;
m_hmoduleDll = ::LoadLibrary(_T("DLLName"));
if (NULL != m_hmoduleDll)
{
bResult = true;
for (int i = 0; i < iNUM_WRAPPED_FUNCTIONS; ++i)
{
switch(arrWrappedFuncs[i].iFunctionSignatureType)
{
case 0:
{
arrWrappedFuncs[i].funcDLLFunc = reinterpret_cast<p2DLLFunc1>(GetProcAddress(m_hmoduleDll, arrWrappedFuncs[i].tcFuncName));
}
break;
case 1:
{
arrWrappedFuncs[i].funcDLLFunc = reinterpret_cast<p2DLLFunc2>(GetProcAddress(m_hmoduleDll, arrWrappedFuncs[i].tcFuncName));
}
break;
default:
{
}
}
if (NULL == arrWrappedFuncs[i].funcDLLFunc)
{
bResult = false;
break;
}
}
if (!bResult)
{
::FreeLibrary(m_hmoduleDll);
}
}
return bResult;
}
The two problems I've got are:
1) How can I store a type in an array, so that I can use it in the reinterpret_cast<> ?
2) What type to define funcDLLFunc in struct MyLUT ?
Not sure about (1), but was thinking of using a union for (2), containing all the different function signatures. Every time a newly wrapped function had a different signature, I would just add a new member to the union and create a new Type.
If it's not possible to store a type in an array, then I guess the only solution is to have a switch statement on iFunctionSignatureType, and then just have the GetProcAddress() line for each type with a different reinterpret_cast<>. However, this is tedious as well, hence my hope for being able to store a type in an array.
Any ideas ?
|
|
|
|
|
Whz do you need reinterpret_cast at the first place? Shouldn't that work without any casting?
> The problem with computers is that they do what you tell them to do and not what you want them to do. <
|
|
|
|
|
Unfortunately not, as you get a compiler error:
error C2440: '=' : cannot convert from 'FARPROC' to 'p2DLLFunc1'
|
|
|
|
|
Try something like:
struct MyLUT {
TCHAR* tcFuncName;
FARPROC *funcDLLFunc;
};
static MyLUT arrWrappedFuncs[] = { {_T("DLLFunc1"), (FARPROC *)&m_funcDLLFunc1},
{_T("DLLFunc2"), (FARPROC *)&m_funcDLLFunc2},
{_T("DLLFunc3"), (FARPROC *)&m_funcDLLFunc3},
};
...
(*arrWrappedFuncs[i].funcDLLFunc) = GetProcAddress(m_hmoduleDll, arrWrappedFuncs[i].tcFuncName));
...
I just modified your code, so it might not compile, and probably needs adjustment here and there but maybe you get the main idea.
> The problem with computers is that they do what you tell them to do and not what you want them to do. <
|
|
|
|
|
FARPROC is defined as a function pointer to a function that receives no input, and returns an int (ie. int func(void)). Therefore, this cannot be used for functions whose parameter list and return type are different (eg. char* func1(int)).
|
|
|
|
|
A pointer in itself is just a memory address, what parameters how are passed upon a call is decided where and when you call the function thorough the pointer, but correct me if i am wrong. Just try this:
void *P1 = (void *)GetProcAddress(DLLHande, "proc_name");
FARPROC P2 = GetProcAddress(DLLHande, "proc_name");
pDLLFunc1 P3 = (pDLLFunc1)GetProcAddress(DLLHande, "proc_name");
pDLLFunc1 P4 = reinterpret_cast<pdllfunc1>(GetProcAddress(DLLHande, "proc_name"));
</pdllfunc1>
And check out the 4 pointer values (for example in the watch window of your debugger if you are using Visual Studio), they all should be the same,
> The problem with computers is that they do what you tell them to do and not what you want them to do. <
|
|
|
|
|
You are correct, and that is the problem. If I don't cast it to the correct type when calling GetProcAddress(), I will have to cast it later on when I call the function pointed to by the pointer. Either way, I will need to cast it at some point. Otherwise I don't think it will let me call it with the relevant parameters and return type.
I will have to do some testing to be sure, but my current understanding makes me think it won't work.
|
|
|
|
|
How about a different aproach, use a template class, something like this:
class CConverterBase
{
public:
virtual operator void =(const FARPROC ptr) = 0;
};
template<typename tfuncptr="">
class CConverter: public CConverterBase
{
TFuncPtr &fFuncPtrPtr;
public:
CConverter(TFuncPtr &ptr):fFuncPtrPtr(ptr) {}
operator void =(const FARPROC ptr)
{
fFuncPtrPtr = (TFuncPtr)ptr;
return fFuncPtrPtr;
}
}
</typename>
And then something like:
class Func
{
TCHAR *pszName;
CConverterBase *ptr;
};
...
Func FuncArr[] = {{_T"DLLFunc1", new CConverter(m_DLLFunc1)}, {_T"DLLFunc2", new CConverter(m_DLLFunc2)}, ...};
...
(*FuncAtt[I].ptr) = GetProcAddress(dllhandle, FuncAtt[I].pszName);
...
And of course don't forget to free up the objects you instantiated.
> The problem with computers is that they do what you tell them to do and not what you want them to do. <
|
|
|
|
|
I've been thinking a similar thing that I might have to use some C++ features to achieve what I'm after. The idea of a template class is good, but the FuncArr[] can only be initialized with static data (ie. known at compile time).
Hmmm, time to put my C++ hat on
|
|
|
|
|
Defenestration wrote: Any ideas ?
Have you read this article on dynamic linking?
"Love people and use things, not love things and use people." - Unknown
"The brick walls are there for a reason...to stop the people who don't want it badly enough." - Randy Pausch
|
|
|
|
|
You can use a MS extension in GetProcAddress() calls:
(FARPROC&) func_ptr = GetProcAddress ( hModule, "FunctionName" ); That way you don't have to make a new typedef for each function pointer.
|
|
|
|
|
I need to send data through a pipe to my main thread and block until the data is read, or until a new command is received from the main thread. It's very important for the write operation to be able to unblock if a new command is available.
There is sufficient light for those who desire to see, and there is sufficient darkness for those of a contrary disposition.
Blaise Pascal
|
|
|
|
|
Hy,
I am still having problem handling some data types and the data itself in memory and so on.
For example: For getting the text of an edit control (winapi) requires to create a buffer with enaugh space. I did (unicode) for example:
length is from the type of WORD in the example, but i used length as an integer.
TCHAR *buf = new TCHAR[length+1];
So now it says the FIRST WORD needs to have the length of the string in the edit field, which I retrieved before.
The example shows:
*((LPWORD)buf) = length;
However, when I use my way: *(buf) = length it ends in the same result.
So, my question is whats so special in the way how msdn do it?
-----
And then, did i understand the line right ? Here is my explanation:
In memory we have allocated space for the variable buf. The length is the length of TCHAR * mylength(the variable)
But in memory it is handled as "we need xx bytes" right?
Then *(buf) points to the first byte (in array it is index 0)
But because we need the first word, we convert the normal pointer (i think normal is a void pointer) to an pointer of a WORD. So now the index 0 for examples is exactly 1 WORD.
Then we write the length variable which is also a WORD to the location.
Is this right or do I misunderstand something?
----
And why is my way *(buf) = length also working?
I hope everybody understand whats my problem. Thank you for help.
bye,
gabbana
|
|
|
|
|
gabbana wrote: I hope everybody understand whats my problem. Thank you for help.
For instance I cannot understand your problem.
To get the text of an edit box, using Windows API , you may to call GetWindowText this way
TCHAR szBuf[0x100];
if (! GetWindowText(hWnd, szBuf, sizeof(szBuf)/sizeof(szBuf[0])))
{
}
If the Lord God Almighty had consulted me before embarking upon the Creation, I would have recommended something simpler.
-- Alfonso the Wise, 13th Century King of Castile.
This is going on my arrogant assumptions. You may have a superb reason why I'm completely wrong.
-- Iain Clarke
[My articles]
|
|
|
|
|
*((LPWORD)buf) = length; - this will copy sizeof(WORD) bytes into the first sizeof(WORD) bytes of your buffer
*(buf) = length - this will convert your integer (length) to a TCHAR and put that into the first TCHAR pointed at by buf.
So let's assume WORD is 2 bytes and TCHAR is also 2 bytes (unicode), in this case the 2 versions should produce the same result, but if you compile wihout unicode, TCHAR being 1 byte then in the second case, only 1 bytes will be changed in your buffer while the 2nd byte is left unchanged, you would probably get a warning from your compiler too ('conversion from int to char, possible loss of data' or similar).
On a sidenote, could you show me where you read this:
gabbana wrote: So now it says the FIRST WORD needs to have the length of the string in the edit field, which I retrieved before.
please?
> The problem with computers is that they do what you tell them to do and not what you want them to do. <
|
|
|
|
|
Okay, now I think i found some information.
Lets start with Bits and Bytes:
A BIT can be 1 or 0. So we have 2 options
A BYTE contains 8 Bits. So we have 2^8 possible option (ASCII/ANSI) So we have all the 256 chars.
A WORD contains 16 Bits (2BYTE)
A WCHAR (wide char) contains also 16bits (2BYTE) -> chinese languag and so on need 2 Bytes for one char.
A Pointer (I said its normally a void point but that was wrong) is normally a pointer to a specific datatype, for example WCHAR *buf -> means we have a Pointer which points to ONE WCHAR somewhere in memory (as long as we allocate space)
So now we allocate space: *buf = new WCHAR[16]; This means we allocate 16 bits per char, so we have allocated 2*16 bytes = 32 bytes which means 2^32 bits.
So if we use the example with edit field, we get an integer (the length) and convert it to a WORD. BECAUSE the edit field must return something >0 we CAN convert it to an unsigned integer, a WORD right?
-> Now why do we need the following?
*((LPWORD)buf) = length
And why does
*(buf) = (WORD)length
also works ?
So we know that WCHAR contains 2Bytes. A WORD also contains 2Bytes.
So the point normaly shows to the firt wchar which is also a WORD in this example. So we can easily move the length to this location. Right ?
But why the first way ?
So it could be that if we does not using unicode, the pinte would only show to the first ONE byte in the memory. And then we need to convert it it first to an LPWORD to be sure the pointer shows to the FIRST 2Bytes, a WORD in memory. And so it works.
I hope its not too long and someone can confirm my explanation.
Thank you very much.
bye,
gabbana
|
|
|
|
|