Ada C绑定到OpenGL函数中的堆栈损坏

ijnw1ujt  于 2023-06-05  发布在  其他
关注(0)|答案(2)|浏览(112)

我使用SDL来检索函数的地址。这看起来是可行的,因为我使用的子程序对所有其他函数调用都有效。
以下是规范中所有相关的代码片段:

type GLenum is new Uint32;

subtype glTexImage2D_Target is GLenum with Static_Predicate => glTexImage2D_Target in GL_TEXTURE_2D | GL_TEXTURE_RECTANGLE | GL_PROXY_TEXTURE_RECTANGLE;
subtype glTexImage2D_Dtype is GLenum with Static_Predicate => glTexImage2D_Dtype in GL_BYTE | GL_UNSIGNED_BYTE;
subtype glTexImage2D_InternalFormat is GLenum with Static_Predicate => glTexImage2D_InternalFormat in GL_DEPTH_COMPONENT | GL_DEPTH_STENCIL | GL_RED | GL_RG | GL_RGB | GL_RGBA;
subtype glTexImage2D_Format is GLenum with Static_Predicate => glTexImage2D_Format in GL_RED | GL_RG | GL_RGB | GL_BGR | GL_RGBA | GL_BGRA | GL_RED_INTEGER | GL_RG_INTEGER | GL_RGB_INTEGER | GL_BGR_INTEGER | GL_RGBA_INTEGER | GL_BGRA_INTEGER | GL_STENCIL_INDEX | GL_DEPTH_COMPONENT | GL_DEPTH_STENCIL;

procedure glTexImage2D(target : glTexImage2D_Target; level : Integer; internalFormat : glTexImage2D_InternalFormat; width : Integer; height : Integer; format : glTexImage2D_Format; dtype : glTexImage2D_Dtype; pixels : System.Address) with Pre => (target /= GL_TEXTURE_RECTANGLE and target /= GL_PROXY_TEXTURE_RECTANGLE) or Level = 0;

procedure Set_OpenGL_Subprogram_Address(Addr : in out System.Address; Name : String);

glTexImage2D_C_Address : System.Address := System.Null_Address;

Could_Not_Load_OpenGL_Subprogram : exception;

以下是正文中的相关片段:

procedure glTexImage2D(target : glTexImage2D_Target; level : Integer; internalFormat : glTexImage2D_InternalFormat; width : Integer; height : Integer; format : glTexImage2D_Format; dtype : glTexImage2D_Dtype; pixels : System.Address) is
begin
    Set_OpenGL_Subprogram_Address(glTexImage2D_C_Address, "glTexImage2D");
    declare
        procedure glTexImage2D_C(target : GLenum; level : GLint; internalFormat : GLint; width : GLsizei; height : GLsizei; border : GLint; format : GLenum; dtype : GLenum; data : System.Address)
        with Import, Convention => Stdcall, Address => glTexImage2D_C_Address;
    begin
        glTexImage2D_C(GLenum(target), GLint(level), GLint(internalFormat), GLsizei(width), GLsizei(height), GLint'(0), GLenum(format), GLenum(dtype), pixels);
    end;
end glTexImage2D;

--This seems to work... but here it is just in case.
procedure Set_OpenGL_Subprogram_Address(Addr : in out System.Address; Name : String) is
begin
    if Addr = System.Null_Address then
        Addr := SDL_GL_GetProcAddress(Value(New_String(Name)));
        if Addr = System.Null_Address then
            raise Could_Not_Load_OpenGL_Subprogram with Name;
        end if;
    end if;
end Set_OpenGL_Subprogram_Address;

最后,我传入的像素是一个地址,表示一个对象的类型:

type Uc_Array is array(Integer range <>) of aliased Interfaces.C.unsigned_char;

调用glTexImage2D_C时堆栈已损坏。我使用gdb发现了这一点:

这里你可以看到我传递的参数;目标3553,级别0,内部格式6408,宽度63,高度63,格式6408,数据类型5121,非零像素地址。子程序地址被设置为非零值。但是在调用glTexImage2D_C之后,$sp(堆栈指针)的值增加了16#24#。
我试着调整传递给glTexImage2D_C的高度和宽度,都是10,都是1000,只是为了看看给它更多(或更少)的缓冲区是否会防止堆栈损坏,但在每种情况下,堆栈指针在过程调用之前和之后都是不同的。
我希望这只是一个简单的错误数据类型或什么的问题...下面是glTexImage2D在OpenGL端的原型:

void glTexImage2D(  GLenum target,
    GLint level,
    GLint internalformat,
    GLsizei width,
    GLsizei height,
    GLint border,
    GLenum format,
    GLenum type,
    const void * data);
  • (最后一点,如果我能让它真正工作的话,我确实打算清理你上面看到的笨拙的懒惰加载策略。现在我将它保留为这种方式,这样我就可以消除在我仍在尝试调试调用本身时尝试调用尚未加载的函数的机会。使用在declare... begin... end块中声明的嵌套过程的策略适用于其他OpenGL函数。)*
toe95027

toe950271#

转到Ada中的glTexImage2D调用,确保传入pixels参数的值(类型Uc_Array)被称为X(X'First)'Address。(这应该与X'Address相同)
其次,确保您的formatdtype参数是正确的-我建议制作一个小型测试台:查找实际值,对它们进行硬编码,然后调用导入的(OpenGL)函数,然后使用一个有效的互操作程序将其“复杂化”到SDL中。
在处理一个新的互操作项目时,在投入之前确保互操作性按预期工作几乎总是更有成效的。(也就是说,不要假设它会“正常工作”。

mi7gmzs6

mi7gmzs62#

我假设你在Windows上,因此你需要检查Stdcall约定是否合适。据我所知,常规的OpenGL库使用C约定。

相关问题