English

How To: Access the SDE C API from Visual Basic

Summary

For those of you who use or want to use Visual Basic to access SDE C API but have come acroos a problem passing pointers to arrays of SDE structures.

This is especially useful for those who want to use MapObjects2 and SDE together. As most MO applications are written in VB, the potential for MO2 and SDE increases. The following Visual Basic code demonstrates how to get around the problem of calling SDE functions that return a list (array) of SDE structures.

Procedure

This example shows you how to get the SE_INSTANCE_LOCK details from a call to SE_instance_get_locks. You should be able to apply the same idea to whatever you need to implement.

Notes on the following sample:
-The code uses the Win API function "CopyMemory".
Refer to MSDN for details on this function
-Where the SDE function calls parameters expect a pointer expect a
pointer to an array of SE_INSTANCE_LOCK, we have defined it as
LONG, i.e. the address of the first element of the expected array.
-Use the Visual Basic function LenB (variable_name) to get the accurate
length, in bytes, of the structure you want to use. See MSDN for more
information. This length is used to increment the base address of the array
to access each subsequent element in the array.
-Save the initial address of your array to another variable;
this is used to free the array later.
-The code was written on Windows NT Service pack 4.0,
Visual Studio 6.x with Service Pack 3, using SDE 3.0.2.1 for Oracle 7.2.

To run this VB sample, you will need a Form with MapObjects 2.x loaded, a Command button, and thr3ee Text boxes. You need to edit the code so it represents your specific SDE server, instance, username and password. If you're not using MapObjects 2.x, then just connect to SDE as normal Set up some instance locas and try it out!

Code:
Option Explicit

' Using MO2 to connect to SDE but you don't need to!

Dim dc As New MapObjects2.DataConnection

'note that the parameters are both long - passing the address of thefirst element of the array

Private Declare Function SE_instance_free_locks Lib "sde30" (ByReflock_list_address As Long, ByVal lock_count As Long) As Long

Private Declare Function SE_instance_get_locks Lib "sde30" (ByVal serverAs String, ByVal instance As String, ByRef address_to_array_of_lock_list_addr As Long, ByRef lock_count_addr AsLong) As Long

'use this Win API call to access the memory for each element in the list array
Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (Destination As Any, Source As Any, ByVal length As Long)
' my definition of SE_INSTANCE_LOCK structure
Private Type SE_INSTANCE_LOCK
pid As Long
layer_id As Integer
lock_type As Long
End Type

Private Sub Command1_Click()
Dim status As Long 'set by SDE
Dim lock_list_addr As Long 'set by SDE API call
Dim sde_lock_count As Long 'set by SDE API call
Dim lock_list_addr_save As Long 'needed to free the list array later
Dim m_lockCount As Integer 'loop iterator

'get the locks from SDE
status = SE_instance_get_locks("drfinlay", "esri_sde", lock_list_addr, sde_lock_count)
' Report the status, list array address and number of locks
Text1.Text = "SDE Error status: " & Str(status)
Text2.Text = "Lock List Address: " & Str(lock_list_addr)
Text3.Text = "Lock Count: " & Str(sde_lock_count)
' save the list address
lock_list_addr_save = lock_list_addr

' declare an array of 200 (max) SE_INSTANCE_LOCK structures
Dim myLocks(200) As SE_INSTANCE_LOCK

' declare an instance of a single lock - used to get the size in Bytes of the structure
Dim aLock As SE_INSTANCE_LOCK

' iterate through all the locks
For m_lockCount = 0 To sde_lock_count - 1

' copy memory from the list array address into myLocks(n), using the length in Bytes
' of a single SE_INSTANCE_LOCK
CopyMemory myLocks(m_lockCount), ByVal lock_list_addr,LenB(aLock)

' Report the details of the nth element of myLocks
MsgBox "Layer ID : " & vbTab & Str(myLocks(m_lockCount).layer_id) & vbNewLine & _
"Lock Type: " & vbTab & Str(myLocks(m_lockCount).lock_type) & vbNewLine & _
"Pid: " & vbTab & vbTab & Str(myLocks(m_lockCount).pid), vbDefaultButton1, "SDE Lock Details"

'increment the lock list array address by the length of a SE_INSTANCE_LOCK structure
lock_list_addr = lock_list_addr + LenB(aLock)

Next m_lockCount

' free the instance locks list array - using the previously saved address
status = SE_instance_free_locks(lock_list_addr_save, sde_lock_count)

End Sub

Private Sub Form_Load()
Command1.Caption = "Get all SDE locks"
Text1.Text = ""
Text2.Text = ""
Text3.Text = ""
Form1.Caption = "SDE Instance Locks example"

' set up MapObjects SDE connection dc.server = "drfinlay"
dc.User = "sde_user"
dc.Password = "sde_user"
dc.Database = "esri_sde"
dc.Connect

End Sub