当传递给非托管C DLL函数时,C#结构变量保持为空

用户名

问题:

我正在为非托管C DLL编写C#包装器。DLL包含一个结构zint_symbol,其中包含一个变量char[] *bitmap在我的C#结构中,我拥有public byte[] bitmap;

这个结构在外部函数传递ZBarcode_Encode_and_Buffer这是应该以呈现PNG图像和位图数据写入到bitmapzint_symbol

当我调用ZBarcode_Encode_and_Buffer并检查时bitmap,它仍然为null

实际上,我的C#结构中应该由DLL写入的每个变量都保持为null

我尝试过的

  1. 编组bitmap为具有很大常数的固定大小的数组,即

    [MarshalAs(UnmanagedType.ByValArray, ArraySubType = UnmanagedType.U1, SizeConst = 25454)]
    public byte[] bitmap; 
    

    ...产生一个SystemAccessViolation

    An unhandled exception of type 'System.AccessViolationException' occurred in mscorlib.dll
    
    Additional information: Attempted to read or write protected memory. This is often an indication     that other memory is corrupt.
    
  2. 将类型更改ibtmapchar[]string这什么都没改变。

  3. [In,Out]装饰器添加到我要传递给C#函数的struct参数中。

  4. 将类型bitmap更改byte[]IntPtr

我不能做的是:

尽管有资源,但我似乎无法编译该库(该项目是开源的,但几年前已被放弃)。这意味着我无法更改C代码。

代码/工作示例

一个小的但完整的工作示例可以在这里下载

包含我的结构的C#类:

class ZintLib
{
    public struct zint_symbol
    {
        public int symbology;

        public int height;
        public int whitespace_width;
        public int border_width;

        public int output_options;

        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 10)]
        public string fgcolour;

        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 10)]
        public string bgcolour;

        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)]
        public string outfile;

        public float scale;
        public int option_1;
        public int option_2;
        public int option_3;
        public int show_hrt;

        public int input_mode;

        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 128)]
        public string text;

        public int rows;
        public int width;

        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 128)]
        public string primary;

        [MarshalAs(UnmanagedType.ByValArray, ArraySubType = UnmanagedType.U1, SizeConst = 25454)]
        public byte[] encoded_data;

        [MarshalAs(UnmanagedType.ByValArray, ArraySubType = UnmanagedType.I4, SizeConst = 178)]
        public int[] row_height;

        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 100)]
        public string errtxt;

        public byte[] bitmap;

        public int bitmap_width;
        public int bitmap_height;
        public IntPtr rendered;
    }

    [DllImport("zint.dll", EntryPoint = "ZBarcode_Create", CallingConvention = CallingConvention.Cdecl)]
    public extern static IntPtr Create();

    [DllImport("zint.dll", EntryPoint = "ZBarcode_Encode_and_Buffer", CallingConvention = CallingConvention.Cdecl)]
    public extern static int EncodeAndBuffer(
      [In, Out] ref zint_symbol symbol,
     String input,
     int length,
     int rotate_angle);
}

调用EncodeAndBuffer的函数:

        // call DLL function to generate pointer to initialized struct
        ZintLib.zint_symbol s = (ZintLib.zint_symbol)

        // generate managed counterpart of struct
        Marshal.PtrToStructure(ZintLib.Create(), typeof(ZintLib.zint_symbol));

        // change some settings
        s.symbology = 71;
        s.outfile = "datamatrix.png";

        // DLL function call to generate output file using changed settings -- WORKS --
        //System.Console.WriteLine(ZintLib.EncodeAndPrint(ref s, "12345", 5, 0));

        // DLL function to generate data in s.bitmap, s.bitmapheight, s.bitmapwidth -- DOES NOT WORK managed struct is unaltered --
        System.Console.WriteLine(ZintLib.EncodeAndBuffer(ref s, (String)"12345", 5, 0));

        if (s.bitmap == null)
            Console.WriteLine("bitmap is null.");
        else
            Console.WriteLine("bitmap is not null.");

C语言中的结构和导出方法:

struct zint_symbol {
    int symbology;
    int height;
    int whitespace_width;
    int border_width;
    int output_options;
    char fgcolour[10];
    char bgcolour[10];
    char outfile[256];
    float scale;
    int option_1;
    int option_2;
    int option_3;
    int show_hrt;
    int input_mode;
    unsigned char text[128];
    int rows;
    int width;
    char primary[128];
    unsigned char encoded_data[178][143];
    int row_height[178]; /* Largest symbol is 177x177 QR Code */
    char errtxt[100];
    char *bitmap;
    int bitmap_width;
    int bitmap_height;
    struct zint_render *rendered;
};

#if defined(__WIN32__) || defined(_WIN32) || defined(WIN32) || defined(_MSC_VER)
#  if defined (DLL_EXPORT) || defined(PIC) || defined(_USRDLL)
#    define ZINT_EXTERN __declspec(dllexport)
#  elif defined(ZINT_DLL)
#    define ZINT_EXTERN __declspec(dllimport)
#  else
#    define ZINT_EXTERN extern
#  endif
#else
#  define ZINT_EXTERN extern    
#endif

ZINT_EXTERN struct zint_symbol *ZBarcode_Create(void);
ZINT_EXTERN void ZBarcode_Clear(struct zint_symbol *symbol);
ZINT_EXTERN void ZBarcode_Delete(struct zint_symbol *symbol);

ZINT_EXTERN int ZBarcode_Encode(struct zint_symbol *symbol, unsigned char *input, int length);
ZINT_EXTERN int ZBarcode_Encode_File(struct zint_symbol *symbol, char *filename);
ZINT_EXTERN int ZBarcode_Print(struct zint_symbol *symbol, int rotate_angle);
ZINT_EXTERN int ZBarcode_Encode_and_Print(struct zint_symbol *symbol, unsigned char *input, int length, int rotate_angle);
ZINT_EXTERN int ZBarcode_Encode_File_and_Print(struct zint_symbol *symbol, char *filename, int rotate_angle);

ZINT_EXTERN int ZBarcode_Render(struct zint_symbol *symbol, float width, float height);

ZINT_EXTERN int ZBarcode_Buffer(struct zint_symbol *symbol, int rotate_angle);
ZINT_EXTERN int ZBarcode_Encode_and_Buffer(struct zint_symbol *symbol, unsigned char *input, int length, int rotate_angle);
ZINT_EXTERN int ZBarcode_Encode_File_and_Buffer(struct zint_symbol *symbol, char *filename, int rotate_angle);

ZINT_EXTERN int ZBarcode_ValidID(int symbol_id);

#ifdef __cplusplus
}
#endif /* __cplusplus */

#endif /* ZINT_H */

注意:在此线程中提出了类似的问题,但从未解决过我已经为此努力了一个星期。有任何想法吗?

大卫·赫弗南(David Heffernan)

您将必须将bitmap成员声明IntPtr并手动封送它。

如果调用方分配了内存,请使用Marshal.AllocHGlobal然后用于Marshal.Copy在非托管内存和您对位图的托管表示之间进行复制。或固定代表位图的托管字节数组。

如果被叫方分配了内存,则只需要Marshal.Copy从非托管复制到托管即可。

这是一个非常复杂的界面,似乎还会出现其他错误。我刚刚看过这个bitmap领域,因为这是您所要求的。

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章

将C#结构传递给非托管C ++ DLL时出现SafeArrayTypeMismatchException

C#将指向结构(包含不可复制类型)的指针传递给非托管C ++ DLL

如何将IntPtr从非托管C ++ CLR托管代码传递给方法?

将非托管方法作为回调传递给托管C ++ / CLI类

使用C#在非托管代码中将委托传递给回调函数

如何将 SOCKET (HANDLE) 从非托管 C 程序传递给 .NET 子进程?

将回调参数从C#传递到非托管C ++

将向量/数组从非托管C ++传递到C#

F#将空值传递给非托管导入的DLL

将字符串编组到非托管内存中,然后将它们传递给C ++,然后再次返回C#

如何在托管(C#)和非托管(C ++)代码之间来回传递数组内容

无法将字符串从托管C#传递到非托管C

使用固定指针将大型数据结构传递给非托管代码

将字节数组从 C++ 非托管 dll 传递到 C# unity

将不同类型的对象传递给非托管函数

为什么在传递给非托管代码时ByRef会给出异常?

在C#中使用非托管DLL

从C#到C-DLL调用/封送该结构时,为什么此字符串为空?

如何将参数传递给用C#编写的托管代码dll的自定义操作?

c-将结构变量传递给函数:segfault

托管和非托管代码之间的传递结构

将结构指针传递给函数c ++

C将结构数组传递给函数

C ++将“默认”结构传递给函数

C 将链表结构传递给函数

使用Mupen64Plus非托管C dll API命令填充C#结构

将结构传递给C#

从C#调用非托管C ++

C ++将变量类型传递给函数