pin_ptr 原生 void* 帮助

发布于 2024-09-29 19:10:21 字数 1227 浏览 2 评论 0原文

设置

我有一个 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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

感情废物 2024-10-06 19:10:21

这没有任何意义。您只能固定托管对象,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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文