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号