pin_ptr 原生 void* 帮助
设置
我有一个 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);
}
我也尝试过固定 buffer[0],但这会导致 GetMetaText 出现访问冲突异常。
问题
我不能说 GetMetaText 中发生了什么,所以我不确定 pdoc 发生了什么。对上面的代码有什么建议吗?
The Setup
I have a PDF API which has a native function that is defined below.
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);
if I call the above code in my C++/CLI wrapper function, it returns the correct string but throws an AccessViolationException when I call PDF_CloseDoc. WOOPS. I forgot to pin_ptr the pointer the document.
The Problem
When I pin_ptr pdoc, i can successfully call these native functions, however the buffer no longer contains my string when PDF_GetMetaText returns.
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);
}
I have also tried pinning buffer[0] but that causes an accessviolation exception at GetMetaText.
The Question
I cant say what is happening in GetMetaText, so I am not sure what is happing to pdoc. Any suggestions to the above code?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
这没有任何意义。您只能固定托管对象,PDF_LoadDoc() 的返回值对我来说肯定看起来不像托管对象。 结果也是如此,它不是托管数组,只是在堆栈帧上分配的普通 C 数组。不幸的是,pin_ptr<>并不抱怨这一点。
如果代码破坏堆栈帧,结果数组只能变为“空”。您可以通过在第一个元素上设置数据断点来诊断。 Fwiw,SystemStringToCStr() 看起来像是一个候选者。如果不释放本地字符串的缓冲区,这将无法工作。另一个候选者是 PDF API 函数声明。注意ESP寄存器的值并确保它没有改变。如果是这样,堆栈就会变得不平衡,因为您没有正确的调用约定。对于 DLL 导出,通常是 __stdcall。
This doesn't make any sense. You can only pin managed objects, the return value of PDF_LoadDoc() sure doesn't look like a managed object to me. Same goes for result, it is not a managed
array<WCHAR>
, just a plain vanilla C array that gets allocated on the stack frame. Unfortunately, pin_ptr<> doesn't complain about this.The result array could only get 'empty' if code is stomping the stack frame. Which you can diagnose by setting a data breakpoint on the first element. Fwiw, SystemStringToCStr() looks like a candidate. This cannot work without releasing the buffer for the native string somewhere. Another candidate is the PDF API function declarations. Pay attention to the value of the ESP register and make sure it doesn't change. If it does, the stack is get imbalanced because you don't have the proper calling convention. Which is usually __stdcall for DLL exports.