Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/320.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/drupal/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C#结构变量在传递到非托管C DLL函数时保持为空 问题:_C#_C_Pinvoke_Dllimport - Fatal编程技术网

C#结构变量在传递到非托管C DLL函数时保持为空 问题:

C#结构变量在传递到非托管C DLL函数时保持为空 问题:,c#,c,pinvoke,dllimport,C#,C,Pinvoke,Dllimport,我正在为非托管C DLL编写一个C#包装器。DLL包含一个结构zint\u符号,其中包含一个变量char[]*位图。在我的C#struct中,我有publicbyte[]位图 此结构被传递到一个外部函数ZBarcode\u Encode\u和\u Buffer,该函数用于渲染PNG图像并将位图数据写入zint\u symbol中的bitmap 当我调用ZBarcode\u Encode\u和\u Buffer并检查位图时,它保持null 事实上,我的C#struct中应该由DLL写入的每个变量都

我正在为非托管C DLL编写一个C#包装器。DLL包含一个结构
zint\u符号
,其中包含一个变量
char[]*位图
。在我的C#struct中,我有
publicbyte[]位图

此结构被传递到一个外部函数
ZBarcode\u Encode\u和\u Buffer
,该函数用于渲染PNG图像并将位图数据写入
zint\u symbol
中的
bitmap

当我调用
ZBarcode\u Encode\u和\u Buffer
并检查
位图
时,它保持null

事实上,我的C#struct中应该由DLL写入的每个变量都保持null

我所尝试的:
  • 位图
    编组为具有非常大常数的固定大小数组,即

    [MarshalAs(UnmanagedType.ByValArray, ArraySubType = UnmanagedType.U1, SizeConst = 25454)]
    public byte[] bitmap; 
    
    …这会导致系统访问冲突
  • 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.
    
  • ibtmap
    的类型更改为
    char[]
    string
    。这并没有改变什么

  • [In,Out]
    装饰器添加到我要传递到C#函数的结构参数中

  • 位图的类型从
    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 */
    

    注意:有人问了一个类似的问题,但没有解决。这件事我已经琢磨了一个星期了。有什么想法吗?

    您必须将
    位图
    成员声明为
    IntPtr
    并手动封送它

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

    如果被调用方分配内存,那么您只需要
    封送.Copy
    将非托管内存复制到托管内存


    这是一个相当复杂的接口,似乎还有其他错误。我刚刚查看了
    位图
    字段,因为这是您询问的内容

    您不能随意将所有这些字段都排除在C#struct声明之外。您需要首先确保Marshal.SizeOf(C#-struct)=SizeOf(C-struct)。@HansPassant为了文章的简洁,我省略了这些字段,但它们在工作示例中。我把它们放回去了。请原谅我的无知,但我如何确保结构匹配的大小?在C++中使用McSal.siZeof来检查大小match@DavidHeffernan我不能编辑C++代码。你可以把头文件编译成一个程序,它发出sisiof的值(Strut ZuttI符号),我把缺失的字段放到我的帖子里,看编辑。(为了缩短文章,我把它们删掉了)。是的,我看到了。我调整了我的答案以匹配。非常有趣。我声明
    bitmap
    IntPtr
    ,在c#调用者中,我使用了
    marshall.allocglobal
    ,然后是
    Marshal.Copy
    。现在我看到了154字节的
    bitmap
    中的数据(适合我正在创建的图像的大小)。但是,
    位图中的数据不是有效的PNG。我的代码中是否有什么东西可能会把它搞砸?我很难说。我不知道库。我找到了它——问题仍然没有解决。每次运行程序,我都会得到不同的(随机)结果我认为这是因为C代码从不向其中写入数据。然而,C库似乎为内存中的数组分配了正确的空间。