我正在为非托管C DLL编写C#包装器。DLL包含一个结构zint_symbol
,其中包含一个变量char[] *bitmap
。在我的C#结构中,我拥有public byte[] bitmap;
。
这个结构在外部函数传递ZBarcode_Encode_and_Buffer
这是应该以呈现PNG图像和位图数据写入到bitmap
在zint_symbol
。
当我调用ZBarcode_Encode_and_Buffer
并检查时bitmap
,它仍然为null。
实际上,我的C#结构中应该由DLL写入的每个变量都保持为null。
编组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.
将类型更改ibtmap
为char[]
和string
。这什么都没改变。
将[In,Out]
装饰器添加到我要传递给C#函数的struct参数中。
将类型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 */
注意:在此线程中提出了类似的问题,但从未解决过。我已经为此努力了一个星期。有任何想法吗?
您将必须将bitmap
成员声明为IntPtr
并手动封送它。
如果调用方分配了内存,请使用Marshal.AllocHGlobal
。然后用于Marshal.Copy
在非托管内存和您对位图的托管表示之间进行复制。或固定代表位图的托管字节数组。
如果被叫方分配了内存,则只需要Marshal.Copy
从非托管复制到托管即可。
这是一个非常复杂的界面,似乎还会出现其他错误。我刚刚看过这个bitmap
领域,因为这是您所要求的。
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句