C# winform调用qrencode的动态库
自己根据qrencode的源码导了一个dll动态库,见:
自己希望能用C#语言调用以下。
首先构建需要的对象:
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
public struct QrCodeLL
{
public int version; ///< version of the symbol
public int width;
public int size;///< width of the symbol
public IntPtr data; ///< symbol data
}
接口:
[DllImport("LLQrencode.dll", EntryPoint = "OutPutQrCodeCSharp", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
public static extern IntPtr OutPutQrCodeCSharp(byte[] bts);//接收参数对应 unsigned char* 也就是二维码内容
使用方法:
public Form1()
{
InitializeComponent();
}
string str = "https://www.cnblogs.com/HelloQLQ/p/16289395.html";
private void button1_Click(object sender, EventArgs e)
{
var byts = Encoding.UTF8.GetBytes(str);
IntPtr ptr = IntPtr.Zero;
var i = TestLL.OutPutQrCodeCSharp(byts);
var qCode = Marshal.PtrToStructure<QrCodeLL>(i);
int size = qCode.width * qCode.width + qCode.width - 1;
byte[] managedArray = new byte[size];
Marshal.Copy(qCode.data, managedArray, 0, size);
var arr = getPngArr(managedArray, qCode.width);
var img = GetMap(arr, qCode.width);
picBox.Image = Magnifier(img, 4);
picBox.Refresh();
}
public byte[] getPngArr(byte[] data, int width)
{
byte[] arr = new byte[data.Length];
int m = 0;
for (int y = 0; y < width; y++)
{
for (int x = 0; x < width; x++)
{
if ((data[y * width + x] & 0x01) == 1)
{
arr[m++] = 0;
}
else
{
arr[m++] = 1;
}
}
}
return arr;
}
public Bitmap GetMap(byte[] arr, int w)
{
Bitmap map = new Bitmap(w, w);
for (int i = 0; i < w; i++)
{
for (int j = 0; j < w; j++)
{
if (arr[i * w + j] == 1)
map.SetPixel(i, j, Color.White);
else
{
map.SetPixel(i, j, Color.Black);
}
}
}
return map;
}
public Bitmap Magnifier(Bitmap srcbitmap, int multiple)
{
if (multiple <= 0) { multiple = 0; return srcbitmap; }
Bitmap bitmap = new Bitmap(srcbitmap.Size.Width * multiple, srcbitmap.Size.Height * multiple);
BitmapData srcbitmapdata = srcbitmap.LockBits(new Rectangle(new Point(0, 0), srcbitmap.Size), ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb);
BitmapData bitmapdata = bitmap.LockBits(new Rectangle(new Point(0, 0), bitmap.Size), ImageLockMode.ReadWrite, PixelFormat.Format32bppArgb);
unsafe
{
byte* srcbyte = (byte*)(srcbitmapdata.Scan0.ToPointer());
byte* sourcebyte = (byte*)(bitmapdata.Scan0.ToPointer());
for (int y = 0; y < bitmapdata.Height; y++)
{
for (int x = 0; x < bitmapdata.Width; x++)
{
long index = (x / multiple) * 4 + (y / multiple) * srcbitmapdata.Stride;
sourcebyte[0] = srcbyte[index];
sourcebyte[1] = srcbyte[index + 1];
sourcebyte[2] = srcbyte[index + 2];
sourcebyte[3] = srcbyte[index + 3];
sourcebyte += 4;
}
}
}
srcbitmap.UnlockBits(srcbitmapdata);
bitmap.UnlockBits(bitmapdata);
return bitmap;
}
运行效果:

总结:
c++使用的 undesign char* 最好是作为接口的返回参数,C#端用IntPtr接收,
接收后,通过Marshal.PtrToStructure(i);转为结构体。
结构体里的指针也是对应c++里的 undesign char*,这样接收:
int size = qCode.width * qCode.width + qCode.width - 1;
byte[] managedArray = new byte[size];
Marshal.Copy(qCode.data, managedArray, 0, size);
需要注意,需要知道接收数组的大小,这里根据源码得知大小是这样算的,其他的话就需要在返回参数里给明白了。
getPngArr,是把数据转为二维码字节数组。
GetMap,原始二维码图像大小
Magnifier,方法二维码图片尺寸。网上抄的。

浙公网安备 33010602011771号