我有一个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。 WOOPS。我忘了将指针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的影响。对上述代码的任何建议?
答案 0 :(得分:2)
这没有任何意义。您只能固定托管对象,PDF_LoadDoc()的返回值肯定对我来说不像托管对象。同样适用于 result ,它不是托管array<WCHAR>
,只是在堆栈帧上分配的普通vanilla C数组。不幸的是,pin_ptr&lt;&gt;不抱怨这个。
如果代码重写堆栈帧,结果数组只能变为“空”。您可以通过在第一个元素上设置数据断点来诊断。 Fwiw,SystemStringToCStr()看起来像候选人。如果没有在某处释放本机字符串的缓冲区,这将无法工作。另一个候选者是PDF API函数声明。注意ESP寄存器的值并确保它不会改变。如果是这样,堆栈将失去平衡,因为您没有正确的调用约定。对于DLL导出,通常是__stdcall。