1

设置

我有一个 PDF API,它具有下面定义的本机函数。

typdef void* PDF_DOCUMENT;
unsigned long PDF_GetMetaText(PDF_DOCUMENT document,
                              const char tag, 
                              void* buffer, 
                              unsigned long bufferlen)

//Calling it "natively" in C++/CLI function to get the PDF Creator tag
WCHAR result[32];
void* pdoc = PDF_LoadDoc("C:\test.pdf");
int numChars = PDF_GetMetaText(pdoc, "Creator", result, 32);
PDF_CloseDoc(pdoc);

如果我在我的 C++/CLI 包装函数中调用上述代码,它会返回正确的字符串,但在我调用 PDF_CloseDoc 时会引发 AccessViolationException。哎呀。我忘了 pin_ptr 指向文档的指针。

问题

当我 pin_ptr pdoc 时,我可以成功调用这些本机函数,但是当 PDF_GetMetaText 返回时缓冲区不再包含我的字符串。

String^ Wrapper::GetCreator(String^ filename)
{
   WCHAR buffer[32];
   void *pdoc = PDF_LoadDoc(SystemStringToCStr(filename));
   pin_ptr<void*> p = &pdoc; //added
   int numPages = PDF_GetMetaText(p, "Creator", buffer, 32);
   PDF_CloseDocument(p); //doesnt crash, but at this line buffer is an empty string

   return gcnew String(buffer);
}

我也尝试过固定缓冲区[0],但这会导致 GetMetaText 出现访问冲突异常。

问题

我不能说 GetMetaText 中发生了什么,所以我不确定 pdoc 发生了什么。对上述代码有什么建议吗?

4

1 回答 1

2

这没有任何意义。您只能固定托管对象,PDF_LoadDoc() 的返回值在我看来肯定不像托管对象。result也是如此,它不是托管的array<WCHAR>,只是一个在堆栈帧上分配的普通 C 数组。不幸的是, pin_ptr<> 并没有抱怨这一点。

如果代码踩踏堆栈帧,则结果数组只能变为“空”。您可以通过在第一个元素上设置数据断点来诊断。Fwiw, SystemStringToCStr() 看起来像一个候选人。如果不在某处释放本机字符串的缓冲区,这将无法工作。另一个候选者是 PDF API 函数声明。注意ESP寄存器的值,确保它不会改变。如果是这样,堆栈就会变得不平衡,因为您没有正确的调用约定。这通常是 __stdcall 用于 DLL 导出。

于 2010-10-28T19:13:43.057 回答