C从dll写入文件,在应用程序中打开文件

时间:2012-09-06 19:37:15

标签: c dll printf

我有一个从dll导出的文件指针,由应用程序初始化(fopen),然后在dll中使用(fprintf)。

问题是fprintf会抛出异常。

DLLFile.c

#define BUILD_FOO
#include "API.H"

File *pFile;

void exportedFunction()
{
   fprintf(pFile,"This will result in an exception\n");//<-This print will crash
}

API.H

#ifdef BUILD_FOO
#    define FOOAPI __declspec(dllexport)
#else
#    define FOOAPI __declspec(dllimport)
#endif

FOOAPI  extern File *pFile;
FOOAPI  void exportedFunction();

APLICATION.C

#undef BUILD_FOO
#include "API.H"
void main()
{
pFile = fopen("path_to_folder","wt");
fprintf(pFile , "This print will work"); // <- This will be printed ok
exportedFunction(); 
}

1从我完成的调试开始,这就是我所看到的:

应用程序中,fopen() _iob [] 指定 pFile 元素。

在调用 fprintf DLL 中,检查 pFile _iob [] ,但应用程序中的 _iob [] 似乎与DLL中的 _iob [] 不同(它们具有不同的地址)。

2我有相同的用例(使用相同的应用程序)和另一个有点类似的DLL,一切正常(_iob []在应用程序和DLL中的相同位置)。

2 个答案:

答案 0 :(得分:1)

这可能是由您的应用程序和DLL disagreeing on which version of the C runtime they're using引起的。除非它们都是针对完全相同版本的C运行时进行编译,否则所有投注都会关闭,并且您不能使用来自另一个的数据调用CRT函数,反之亦然。

避免此问题的最安全方法是不要在DLL边界之间传递FILE*指针。这样,与FILE*的任何交互都将始终使用相同版本的CRT进行,并且不存在任何不匹配的危险。所以你的DLL不应该公开FILE*变量;相反,它应该是一些不透明的类型,并且变量上的所有操作都需要在同一个模块中进行。

例如:

// API.h
FOOAPI void set_file(void *file);
FOOAPI void set_fprintf_callback(int (*my_fprintf)(void *, const char *, ...));
FOOAPI void exportedFunction();

// DLLFile.c
void *pFile;  // Not exported
int (*fprintf_callback)(void *, const char *, ...);  // Not exported

FOOAPI set_file(void *file)
{
    pFile = file;
}

FOOAPI set_fprintf_callback(int (*my_fprintf)(void *, const char *, ...))
{
    fprintf_callback = my_fprintf;
}

FOOAPI exportedFunction()
{
    // Call back into the application to do the actual fprintf
    fprintf_callback(pFile, "This should not crash");
}

// Application.c
int mydll_fprintf(void *pFile, const char *fmt, ...)
{
    va_list ap;
    va_start(ap, fmt);
    int result = vfprintf((FILE *)pFile, fmt, ap);
    va_end(ap);

    return result;
}

int main()
{
    FILE *pFile = fopen(...);
    set_file(pFile);
    set_fprintf_callback(&mydll_fprintf);
    exportedFunction();

    return 0;
}

答案 1 :(得分:0)

让应用程序向DLL传递一个回调,并在该回调中让应用程序写入该文件。