作为我之前问题的后续内容,我终于将C dll导出并在C#中可用,但我仍然试图弄清楚正确的参数类型和调用方法。
我在这里研究了SO,但似乎没有关于如何分配变量类型的模式。
我看到有些人建议StringBuilder
为uchar*
,其他人为byte[]
,有些人提及“不安全”代码,等等。任何人都可以推荐基于此的解决方案具体用例?
另请注意,在调用C函数之后,代码就会立即生成异常。
C函数导入:
[DllImport("LZFuncs.dll")]
internal static extern long LZDecomp(ref IntPtr outputBuffer, byte[] compressedBuffer, UInt32 compBufferLength); //Originally two uchar*, return is size of uncompressed data.
C函数签名:
long LZDecomp(unsigned char *OutputBuffer, unsigned char *CompressedBuffer, unsigned long CompBufferLength)
使用如下:
for (int dataNum = 0; dataNum < _numEntries; dataNum++)
{
br.BaseStream.Position = _dataSizes[dataNum]; //Return to start of data.
if (_compressedFlags[dataNum] == 1)
{
_uncompressedSize = br.ReadInt32();
byte[] compData = br.ReadBytes(_dataSizes[dataNum] - 4);
IntPtr outData = IntPtr.Zero;
LZFuncs.LZDecomp(ref outData, compData, Convert.ToUInt32(compData.Length));
var uncompData = new byte[_uncompressedSize]; //System.ExecutionEngineException was unhandled
Marshal.Copy(outData, uncompData, 0, Convert.ToInt32(_uncompressedSize));
BinaryWriter bw = new BinaryWriter(new FileStream("compData" + dataNum + ".txt", FileMode.CreateNew));
bw.Write(uncompData);
bw.Close();
}
else
{
BinaryWriter bw = new BinaryWriter(new FileStream("uncompData" + dataNum + ".txt", FileMode.CreateNew));
bw.Write(br.ReadBytes(_dataSizes[dataNum]));
bw.Close();
}
}
我认为,如果C代码破坏了C#调用者,那么C代码会严重破坏内存,但是由于C代码的编写方式,在没有破坏功能的情况下绝对没有办法修改它,它是实际上是一个黑盒子。 (大部分是用大会写的。)
作为参考,我只是为了解决这个问题而阅读了几个问题:
How do I return a byte array from C++ to C#
Correct way to marshall uchar[] from native dll to byte[] in c#
还有其他人,但这些是最新的。
答案 0 :(得分:1)
好的,这不太难以使用。两个缓冲区参数是字节数组。您应该将它们声明为byte[]
。调用约定是Cdecl
。请记住,C ++ long
在Windows上只有32位宽,所以使用C#int
而不是C#long
,因为后者是64位宽。
声明这样的函数:
[DllImport("LZFuncs.dll", CallingConvention = CallingConvention.Cdecl)]
internal static extern int LZDecomp(
[Out] byte[] outputBuffer,
[In] byte[] compressedBuffer,
uint compBufferLength
);
您正在将compressedBuffer
解压缩为outputBuffer
。你需要知道outputBuffer
需要多大(问题中的代码表明你已经处理过这个)并分配一个足够大的数组。除此之外,我认为如何称呼它是显而易见的。
调用代码如下所示:
_uncompressedSize = br.ReadInt32();
byte[] compData = br.ReadBytes(_dataSizes[dataNum] - 4);
byte[] outData = new byte[_uncompressedSize];
int len = LZFuncs.LZDecomp(outData, compData, (uint)compData.Length);
答案 1 :(得分:0)
这是一个老问题,但却是一个真正的问题,可能会导致严重的安全问题,所以我想我给它 2 美分
每当我使用 [DllImport] 时,我总是添加您认为安全的位置,一种选择是指定用于 Windows DLL 的位置
[DefaultDllImportSearchPaths(DllImportSearchPath.SafeDirectories)]
但是,查看您的选项以使其符合您的需求,您可能会加载位于其他地方的私有 DLL。