C#调用C函数库,如何向char**类型的参数传递数据?
C#调用C函数库,如何向char**类型的参数传递数据?
在C#调用openGL函数时,有下面这个不得不使用的函数:
// C语言:为shader(代号为name)指定其源代码codes
void glShaderSource(GLuint name, GLsizei count, char** codes, GLint* lengths);
其对应的C#声明和实现如下:
// byte** in C# matches char** in C
public static unsafe void glShaderSource(GLuint name, GLsizei count, byte** codes, GLint* lengths) {
var context = SoftGL.GetCurrentContextObj();
if (context == null) { return; }
if (name == 0) { context.lastErrorCode = (uint)(ErrorCode.InvalidValue); return; }
if (!context.name2Shader.TryGetValue(name, out var shader)) { context.lastErrorCode = (uint)(ErrorCode.InvalidOperation); return; }
if (count < 0) { context.lastErrorCode = (uint)(ErrorCode.InvalidValue); return; }
var builder = new System.Text.StringBuilder();
for (int i = 0; i < count; i++) {
var str = codes[i];//每个codes[i]都代表一个string,是源代码的一部分
var length = lengths[i];//lengths[i]是codes[i]这个string的字符数量
for (int j = 0; j < length; j++) {
var c = (char)str[j];//将byte转换为char
builder.Append(c);
}
builder.AppendLine();
}
shader.Code = builder.ToString();
}
这里要注意,C语言中的
char是1个字节,而C#中的char是2个字节,C#中的byte才是与C语言中的char对应的类型。
所以,必须用byte**表示C语言函数参数中的char**。
在调用此函数时,要将string[]转换为byte**,代码如下:
public static unsafe Shader? Create(string[] sourceSegments) {
...
var codes = stackalloc byte*[sourceSegments.Length];
for (int i = 0; i < sourceSegments.Length; i++) {
// 将string复制到非托管内存
codes[i] = (byte*)Marshal.StringToHGlobalAnsi(sourceSegments[i]);
}
var lengths = stackalloc GLint[sourceSegments.Length];
for (int i = 0; i < sourceSegments.Length; i++) {
lengths[i] = sourceSegments[i].Length;
}
gl.glShaderSource(shaderId, sourceSegments.Length, codes, lengths);
// 释放非托管内存
for (int i = 0; i < sourceSegments.Length; i++) { Marshal.FreeHGlobal((IntPtr)codes[i]); }
...
}
这里要注意,必须使用
Marshal.StringToHGlobalAnsi(),而不是Marshal.StringToHGlobalAuto()或Marshal.StringToHGlobalUni()。
当然,可以用IntPtr*代替byte**。
|
微信扫码,自愿捐赠。四海同道,共谱新篇。
微信捐赠不显示捐赠者个人信息,如需要,请注明联系方式。 |

浙公网安备 33010602011771号