Intel® Fortran Compiler
Build applications that can scale for the future with optimized code designed for Intel® Xeon® and compatible processors.

Interfacing C++ stuff (AVIFile API)

andrew_4619
Honored Contributor III
1,074 Views

In my application I have rendered a series of dynamic images in OpenGL. I dumped this data as a series of bitmaps and then used an external program to make a movie. Looking at the AVIFile API's it seemed not so big a step to just encode the data to create and AVI directly. It is not quite
working as yet and as I'm well outside of my comfort zone I have some basic questions regarding getting this stuff to work with Fortran. Consider the MSDN C++ sample below:

// LoadAVIFile - loads AVIFile and opens an AVI file. 
// 
// szfile - filename 
// hwnd - window handle 
// 
VOID LoadAVIFile(LPCSTR szFile, HWND hwnd) 
{ 
    LONG hr; 
    PAVIFILE pfile; 
 
    AVIFileInit();          // opens AVIFile library 
 
    hr = AVIFileOpen(&pfile, szFile, OF_SHARE_DENY_WRITE, 0L); 
    if (hr != 0){ 
        // Handle failure.
        return; 
    } 
 
// 
// Place functions here that interact with the open file. 
// 
 
    AVIFileRelease(pfile);  // closes the file 
    AVIFileExit();          // releases AVIFile library 
}

From the AVIFileopen in Fortran I get back Pointer that  points to a buffer that receives the new IAVIFile interface pointer (&pfile). Note in the C++ this looks at a type PAVIFILE. My question is what does Fortran need to understand about this type? To my (probably flawed) thinking I need some memory buffer for whatever object it points at? From a pratical point of view I do not need to know anything about these objects as the pointers are just used to pass into other routines in that family

From vfw.h we have:

#define INTERFACE IAVIFile
#define PAVIFILE IAVIFile *
  DECLARE_INTERFACE_(IAVIFile,IUnknown) {
    STDMETHOD(QueryInterface) (THIS_ REFIID riid,LPVOID *ppvObj) PURE;
    STDMETHOD_(ULONG,AddRef) (THIS) PURE;
    STDMETHOD_(ULONG,Release) (THIS) PURE;
    STDMETHOD(Info) (THIS_ AVIFILEINFOW *pfi,LONG lSize) PURE;
    STDMETHOD(GetStream) (THIS_ PAVISTREAM *ppStream,DWORD fccType,LONG lParam) PURE;
    STDMETHOD(CreateStream) (THIS_ PAVISTREAM *ppStream,AVISTREAMINFOW *psi) PURE;
    STDMETHOD(WriteData) (THIS_ DWORD ckid,LPVOID lpData,LONG cbData) PURE;
    STDMETHOD(ReadData) (THIS_ DWORD ckid,LPVOID lpData,LONG *lpcbData) PURE;
    STDMETHOD(EndRecord) (THIS) PURE;
    STDMETHOD(DeleteStream) (THIS_ DWORD fccType,LONG lParam) PURE;
  };

#undef PAVIFILE
  typedef IAVIFile *PAVIFILE;

#undef INTERFACE 

If this was POD (plain old data) I would define a type and the way forward would be clear but all this C++ method stuff.....???
What is one meant to do? Some "pointers" would be most helpful!

Andrew

0 Kudos
6 Replies
IanH
Honored Contributor III
1,074 Views

It's not really C++ method stuff.

It's far worse.

It's COM (or COM lite).

But don't despair... inspection of the API (I don't know it at all) shows that wrapper functions have been provided (AVIFileReadData, etc...).  You can just treat the returned pointer as an opaque handle (a C_PTR, perhaps) and you don't need to know what it points at.  Easy!

(Those wrapper functions might be implemented in the lib, rather than in the DLL, didn't check.)

Maybe (just to illustrate - mistakes probable):

INTERFACE
  FUNCTION AVIFileOpen(ppfile, szFile, mode, pclsidHandler)
    USE, INTRINSIC :: ISO_C_BINDING, ONLY: C_PTR, C_INT, C_LONG
    IMPLICIT NOT MANY
    !DEC$ ATTRIBUTES ALIAS:'AVIFileOpenA' :: AVIFileOpen
    !DEC$ ATTRIBUTES STDCALL :: AVIFileOpen
    TYPE(C_PTR), INTENT(OUT) :: ppfile   ! this one by reference
    !DEC$ ATTRIBUTES REFERENCE :: ppfile
    CHARACTER(*), INTENT(IN) :: szFile   ! null terminate this!
    !DEC$ ATTRIBUTES REFERENCE :: sFile  ! no length please compiler.
    INTEGER(C_INT), INTENT(IN) :: mode
    TYPE(C_PTR), INTENT(IN) :: pclsidHandler
    INTEGER(C_LONG) :: AVIFileOpen
  END FUNCTION AVIFileOpen
  
  FUNCTION AVIFileWriteData(pfile, ckid, lpData, cbData)
    USE, INTRINSIC :: ISO_C_BINDING, ONLY: C_PTR, C_LONG
    IMPLICIT NONE
    !DEC$ ATTRIBUTES ALIAS:'AVIFileWriteData' :: AVIFileWriteData
    !DEC$ ATTRIBUTES STDCALL :: AVIFileWriteData
    TYPE(C_PTR), INTENT(IN) :: pfile    ! this one by value.
    INTEGER(C_LONG), INTENT(IN) :: ckid
    TYPE(C_PTR), INTENT(IN) :: lpData
    INTEGER(C_LONG), INTENT(IN) :: cbData
    INTEGER(C_LONG) :: AVIFileWriteData
  END FUNCTION AVIFileWriteData
END INTERFACE

TYPE(C_PTR) :: my_file_handle
INTEGER(C_LONG) :: the_result

the_result = AVIFileOpen( my_file_handle, 'my avi file.avi' // ACHAR(0),  &
    something_here, C_NULL_PTR )
the_result = AVIFileWriteData( my_file_handle, i_have_no_idea,  &
    C_LOC(your_data), perhaps_C_SIZEOF(your_data) )

It is also possible to delve into the underlying COM layer from Fortran, if you want or need to (you have to do that for things like Direct2D).

(Edit - forgot !DEC$ ATTRIBUTES DECORATE, probably other stuff...)

0 Kudos
Steven_L_Intel1
Employee
1,074 Views

"IMPLICIT NOT MANY" ? That's a new one on me...

0 Kudos
andrew_4619
Honored Contributor III
1,074 Views

IanH wrote:

It's far worse.

It's COM (or COM lite).

But don't despair... inspection of the API (I don't know it at all) shows that wrapper functions have been provided (AVIFileReadData, etc...).  You can just treat the returned pointer as an opaque handle (a C_PTR, perhaps) and you don't need to know what it points at.  Easy!

Thanks a lot for the info, you have confirmed what I was thinking, "opaque handle", I like that terminology. I had made interfaces for about 9 of the AVI File/stream family and some  top level Fortran routines (set-up streams, compression etc, write buffers x n, tidy up after) and was not getting total joy when running the code so I was trying to sense check what I was doing. I have only briefly revisited this as a another priority has come up but I think my problems are due to POBs (plain old bugs) and I just need to go through the code and interfaces again carefully.

Thanks agian

Andrew

 

 

0 Kudos
mecej4
Honored Contributor III
1,074 Views

Steve Lionel (Intel) wrote:

"IMPLICIT NOT MANY" ? That's a new one on me...

I think that it is a bit weaker than IMPLICIT ALMOST NONE.

0 Kudos
Mincheol_L_
Beginner
1,074 Views

Hello app4619

I am so interest in this topic.
Did you make some progress?
If it is not disturbing you, could you share the code for everyone who interested in that kind of works?

Thanks a lot.

0 Kudos
andrew_4619
Honored Contributor III
1,074 Views

Mincheol L. wrote:

Hello app4619

I am so interest in this topic.
Did you make some progress?
If it is not disturbing you, could you share the code for everyone who interested in that kind of works?

Thanks a lot.

I didn't spend any more time on that so it was not working, I will go back to it at some point but it is not a priority at the moment. There are a couple of resources where people have written a C++ class where it might just be easier to interface that to Fortran instead maybe. My preference is to keep everything in one language.

 

0 Kudos
Reply