FILE * stream in .DLL loaded from LoadLibrary() doesn't work

O

one2001boy

Hello,

I can use call a function with any arugment from LoadLibrary(),
but not a function with argument of "FILE*.

For example, I can build a .DLL dynamically loaded library with
option /DDD in VC++ in command link.exe.
This dynamically loaded library can then be loaded by
function LoadLibrary(). The address of a function say
func1(int) inside .DLL file can be exported and accessed by function
GetProcAddress(). I can then invokde the function inside
..DLL through a pointer to function. Also, the argument
can be passed from the main program to the function as shown below.

void *dll;
dll = LoadLibrary("mydll.dll");
void (*fp1)(int);
fp1 = (void (*)(int))GetProcAddress(dll, "func1");
fp1(10);

However, if the argument of a function say, func2() is
FILE *. Then, the program will crash as shown below.

FILE* s;
s = fopen("test")
void (*fp2)(FILE*);
fp2 = (void (*)(int))GetProcAddress(dll, "func2");
fp2(stdout); // or fp2(s) will crash.

It appears that the mydll.dll has separate FILE streams
and they are overlap with the application program with file
extension .exe. How can it be resloved?

Does anyone know how to handle this passing FILE* to
a function inside a .DLL loaded by LoadLibrary()?

Thank you in advance for your help.
 
C

Carl Daniel [VC++ MVP]

Hello,

I can use call a function with any arugment from LoadLibrary(),
but not a function with argument of "FILE*.

For example, I can build a .DLL dynamically loaded library with
option /DDD in VC++ in command link.exe.
This dynamically loaded library can then be loaded by
function LoadLibrary(). The address of a function say
func1(int) inside .DLL file can be exported and accessed by function
GetProcAddress(). I can then invokde the function inside
.DLL through a pointer to function. Also, the argument
can be passed from the main program to the function as shown below.

void *dll;
dll = LoadLibrary("mydll.dll");
void (*fp1)(int);
fp1 = (void (*)(int))GetProcAddress(dll, "func1");
fp1(10);

However, if the argument of a function say, func2() is
FILE *. Then, the program will crash as shown below.

FILE* s;
s = fopen("test")
void (*fp2)(FILE*);
fp2 = (void (*)(int))GetProcAddress(dll, "func2");
fp2(stdout); // or fp2(s) will crash.

It appears that the mydll.dll has separate FILE streams
and they are overlap with the application program with file
extension .exe. How can it be resloved?

Link both your EXE and all of your DLLs with the "Multi-threaded DLL"
runtime library (msvcrt.lib). You have two (or more) sets of FILE streams
because your application (when taken in total) has two (or more) copies of
the C runtime library in memory.

-cd
 
C

clyclopedic

inline..

Hello,

I can use call a function with any arugment from LoadLibrary(),
but not a function with argument of "FILE*.

For example, I can build a .DLL dynamically loaded library with
option /DDD in VC++ in command link.exe.
This dynamically loaded library can then be loaded by
function LoadLibrary(). The address of a function say
func1(int) inside .DLL file can be exported and accessed by function
GetProcAddress(). I can then invokde the function inside
.DLL through a pointer to function. Also, the argument
can be passed from the main program to the function as shown below.

void *dll;
dll = LoadLibrary("mydll.dll");
void (*fp1)(int);
fp1 = (void (*)(int))GetProcAddress(dll, "func1");
fp1(10);

However, if the argument of a function say, func2() is
FILE *. Then, the program will crash as shown below.

FILE* s;
s = fopen("test")
void (*fp2)(FILE*);

Above you declare the function pointer fp2 to point to a function that takes
a FILE * argument.
fp2 = (void (*)(int))GetProcAddress(dll, "func2");

Above you cast the return from GetProcAddress to a pointer to a function
that takes an int argument. This conflicts with the FILE * you should be
working with.

Do yourself a favor and create a header file that is included in both
compilations. This is a fundamental principle of maintaining your sanity
when working out interfaces. Create a typedef for fp2 in your header file:

typedef void (*FP2PROC) (FILE *);

Use the typedef in your code:

FP2PROC fp2;
fp2 = (FP2PROC)GetProcAddress(...);
fp2(stdout); // or fp2(s) will crash.

It appears that the mydll.dll has separate FILE streams
and they are overlap with the application program with file
extension .exe. How can it be resloved?

I don't think your problem has to do with separate FILE streams or multiple
copies of the runtime.
 
O

one2001boy

Carl said:
Link both your EXE and all of your DLLs with the "Multi-threaded DLL"
runtime library (msvcrt.lib). You have two (or more) sets of FILE streams
because your application (when taken in total) has two (or more) copies of
the C runtime library in memory.

In my code, I had

extern char ** __cdecl environ;

Now, when I link the code with the .obj compiled with
option /MD based on your suggestion, it will complain that
the symbol _environ cannot be found. how to fix it?

Thank you for your help.
 
O

one2001boy

clyclopedic said:
inline..




Above you declare the function pointer fp2 to point to a function that takes
a FILE * argument.




Above you cast the return from GetProcAddress to a pointer to a function
that takes an int argument. This conflicts with the FILE * you should be
working with.

Thanks for your suggestion.

It is my typo with int.

Do yourself a favor and create a header file that is included in both
compilations. This is a fundamental principle of maintaining your sanity
when working out interfaces. Create a typedef for fp2 in your header file:

typedef void (*FP2PROC) (FILE *);

Use the typedef in your code:

FP2PROC fp2;
fp2 = (FP2PROC)GetProcAddress(...);




I don't think your problem has to do with separate FILE streams or multiple
copies of the runtime.

use carl's suggestion to compile with /MD works.

Thanks.
 
C

Carl Daniel [VC++ MVP]

In my code, I had

extern char ** __cdecl environ;

Now, when I link the code with the .obj compiled with
option /MD based on your suggestion, it will complain that
the symbol _environ cannot be found. how to fix it?

IIUC, you should be using the _putenv() and _getenv() rather than accessing
_environ directly.

-cd
 
O

one2001boy

Carl said:
IIUC, you should be using the _putenv() and _getenv() rather than accessing
_environ directly.

These two funcs can be used only when you know the variable names.
If not, _environ contains all and should be used.

Thanks. I have fixed this problem.
 
O

one2001boy

Link both your EXE and all of your DLLs with the "Multi-threaded DLL"
runtime library (msvcrt.lib). You have two (or more) sets of FILE streams
because your application (when taken in total) has two (or more) copies of
the C runtime library in memory.

After linking with /MD, it requires to have MSVCR71.dll
in Win 9x and Win2000 to be able to run. Does it mean that MSVCR71.dll
is required to distribute with binary code together for machines with
no .NET installed?

Thanks.
 
C

Carl Daniel [VC++ MVP]

After linking with /MD, it requires to have MSVCR71.dll
in Win 9x and Win2000 to be able to run. Does it mean that MSVCR71.dll
is required to distribute with binary code together for machines with
no .NET installed?

msvcr71.dll should be distributed with your application - it's not part of
..NET, but rather part of VC++. You were able to get away with not
distributing the runtime DLL with VC6 applications because msvcrt.dll is
also included in the operating system itself.

-cd
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top