什么是Net互操作?.Net不能直接操作非托管代码,这时就需要互操作了。
   c#中调用非托管c++函数,此函数又包含指向某个结构的指针,譬如指向c#中的byte数组。对于这样的参数,考虑到非托管变量不能直接在托管代码中使用,那么应该如何去处理呢?

上例子:

 private string getSelText(int start,int Scount)
{
try
{
StringBuilder a = new StringBuilder(Scount); IntPtr pdf_pag = FPDFView.FPDF_LoadPage(pdf_doc, currentPage);
IntPtr cur_textpag = FPDFText.FPDFText_LoadPage(pdf_pag);
int count=Scount/;
for (int i = ; i <= count; i++)
{
byte[] copyText = new byte[];//托管数组
IntPtr pdata = Marshal.AllocHGlobal();//申请内存
Marshal.Copy(copyText, , pdata, );//再向里copy数据
if (i != Scount / )
{
FPDFText_GetText(cur_textpag, start + i * , , copyText);//非托管c++函数,参数copyText是带有返回数据的非托管数组
}
else
{
FPDFText_GetText(cur_textpag, start + i * , Scount % , copyText);
}
Marshal.FreeHGlobal(pdata);//以及释放内存
a.Append( UnicodeEncoding.Unicode.GetString(copyText)); } DeleteObject(pdf_pag);
DeleteObject(cur_textpag);
return a.ToString();
}
catch (Exception ex)
{ MessageBox.Show(ex.Message);
return null;
} }

(此处需注意的是:需要非托管指针byte[]参数的内存要先申请,再向里copy数据;还有最后要记得释放申请的内存. )

细心的读者可能会发现方法中有总的数据长度,为什么要分n个固定长度去读取呢?这是因为要操作的数据过大时,程序就会报内存不够用的错误,所以使用小数组循环读取,避免此问题的出现。可为什么数组长度是1024,而每次读取的长度是512呢?假如我们使用长度为512的数组 结果会怎样呢?

答案是只会返回一部分字符串数据,那缺少的部分哪去了呢,问题出在哪呢?

很容易也很关键的就想到,byte[]长度不够,字符数据被截取了,问题很可能就出在c++非托管代码返回的数据类型与c#托管代码数据类型不一致造成的偏差(定义函数的人真坑)。我们转到定义查看FPDFText_GetText的声明。

c#代码:

[DllImport("fpdfsdk.dll", CharSet = CharSet.Unicode)]
        public static extern int FPDFText_GetText(IntPtr text_page, int start_index, int count, byte[] result);

没错啊,byte[] 类型的,让我们再来看下关于此非托管函数的c++文档说明:

DLLEXPORT int STDCALL FPDFText_GetText ( FPDF_TEXTPAGE  text_page,
    int  start_index,
    int  count,
    unsigned short *  result 
  )

答案出现了, c++的unsigned short类型的指针能不能用c#中byte[]类型承接?查资料 ,非托管c++unsigned short与c#中的  System.UInt16是等价的,均是 16 位的,而c#的byte是8位的,难怪总是出现数据丢失的现象。

该怎么解决呢?由于c#中没有现成的UInt16转字符串的方法,唯有抛弃UInt16,改用原来的byte,只要每次读入固定的长度,而承接的byte[]的长度是该长度的两倍即可。

另一种解决办法是使用Marshal.PtrToStringUni(ptr)转化,代码如下:

 int BufferLength = ;
BufferLength = FPDFText.FPDFText_PageToText(pdf_doc, CurrentPage, IntPtr.Zero, , );
IntPtr ptr = Marshal.AllocCoTaskMem(BufferLength * sizeof(UInt16));//申请内存大小,Uint16,16位等价于c/c++中wchar_t,unsigned short
FPDFText.FPDFText_PageToText(pdf_doc, CurrentPage, ptr, BufferLength, );
string str = Marshal.PtrToStringUni(ptr);

.Net调用非托管代码数据类型不一致的问题的更多相关文章

  1. C#如何直接调用非托管代码

    C#如何直接调用非托管代码,通常有2种方法: 1.  直接调用从 DLL 导出的函数. 2.  调用 COM 对象上的接口方法 我主要讨论从dll中导出函数,基本步骤如下: 1.使用 C# 关键字 s ...

  2. java.sql.SQLException: ORA-00932: 数据类型不一致: 应为 -, 但却获得 CLOB

    总是报:ORA-00932: 数据类型不一致: 应为 -, 但却获得 CLOB 是由于这个a.progressAndPlan字段clob字段. 第一种解决方法: a.progressAndPlan 改 ...

  3. SQL Server ->> 数据类型不一致比较时的隐式转换

    当使用操作符进行比较的时候,两边数据类型不一致的情况下,数据类型优先级别低的会往优先级别高的发生隐式转换.下面的参考链接是优先级别列表. 参考: Data Type Precedence (Trans ...

  4. C# 直接调用非托管代码的方法

    C# 代码有以下两种可以直接调用非托管代码的方法: 直接调用从 DLL 导出的函数. 调用 COM 对象上的接口方法. 对于这两种技术,都必须向 C# 编译器提供非托管函数的声明,并且还可能需要向 C ...

  5. DB字段顺序与类的属性顺序一致:{Oracle.DataAccess.Client.OracleException ORA-00932: 数据类型不一致: 应为 TIMESTAMP, 但却获得 NUMBER

    {Oracle.DataAccess.Client.OracleException ORA-00932: 数据类型不一致: 应为 TIMESTAMP, 但却获得 NUMBER     应用程序中类型T ...

  6. Oracle关联查询-数据类型不一致问题 ORA-01722: 无效数字

    一.存在表A和表B,都包含字段user_no,但数据类型不一致,如下: create table A ( user_id varchar2(20), user_no number(12,0), xxx ...

  7. Caused by: java.sql.SQLSyntaxErrorException: ORA-00932: 数据类型不一致: 应为 NUMBER, 但却获得 BINARY

    at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvo ...

  8. java.sql.SQLSyntaxErrorException: ORA-00932: 数据类型不一致: 应为 NUMBER, 但却获得 BINARY

    2019-07-24 17:24:35 下午 [Thread: http-8080-4][ Class:net.sf.ehcache.store.disk.Segment Method: net.sf ...

  9. C# 调用c++数据类型对应

    C#调用 非托管C++ dll 传入Stringbuilder.ref string . ref char 等都报错,如mscorlib.dll 异常.其他信息: 尝试读取或写入受保护的内存.这通常指 ...

随机推荐

  1. 关于$.ajax中data字段的整理--包括json转换和spring注解

    1.前端$.ajax 的data为json提交的时候,后台方法中必须使用@RequestBody 注解    @RequestMapping(value = "getCpuData/{int ...

  2. objective-c 一个链式加法计算器实现

    一个链式加法计算器实现思路 1.使用时的效果 Calculate * manger=[Calculate new]; int result=manger.add(123).add(123).sub(1 ...

  3. ABBYY FineReader的图像编辑器功能使用方法

    日常工作中,有时可能需要对图像进行编辑,可是正常情况下大家都知道图像是不能直接编辑的,需要借助工具.ABBYY FineReader 12 OCR文字识别软件可以实现图像的手动编辑,接下来就具体给大家 ...

  4. 【转】GridView中页脚汇总显示

    来源:http://blog.csdn.net/atian15/article/details/3495514 有时候需要在GridView的页脚中汇总显示一些信息,常见的方法有两种: 1.在SQL中 ...

  5. xml学习笔记二(规则)

    XML 的语法规则很简单,且很有逻辑.这些规则很容易学习,也很容易使用. 所有 XML 元素都须有关闭标签 在 HTML,经常会看到没有关闭标签的元素: <p>This is a para ...

  6. 数据结构线性表(js实现)

    最近在复习数据结构的过程中,发现基本上数据结构都是用C来实现的,自己之前学习的时候也是用C去写的,由于目前对js更为熟悉一些,所以这里选择使用js去实现其中的某些算法和结构.实际上算法和语言关系不大, ...

  7. Oracle查找表的外键引用关系

    Oracle查找表的外键引用关系 select t1.table_name, t2.table_name as "TABLE_NAME(R)", t1.constraint_nam ...

  8. hibernate 自生双向一对多 多对一管理 (树)

    <span style="font-size: large;">package com.javacrazyer.test; import java.io.Seriali ...

  9. Java自带工具jstack故障分析的一个案例

    公司的一个web应用项目运行了很长一段时间,达半年之久,前段时间突然出现了服务不可用的情况,所有的请求都不可达,服务彻底挂了.查看tomcat进程还在,cpu使用率低,一时没找着问题,重启了服务.过了 ...

  10. MyEclipse Hibernate 学习总结

    最近在学习Hibernate,先把学习的过程记录一下,方便自己以后复习. 1.使用工具 MyEclipse 10 2. 1)新建Java程序 2)右键程序,选择MyEclipse-> Add H ...