I'm creating a program that will create a service with description. My current code is able to create a service but not be able to create its description. My current code
Module:
Option Explicit
Private Declare Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long)
Private Const ERROR_SERVICE_DOES_NOT_EXIST = 1060&
Private Const SERVICE_WIN32_OWN_PROCESS = &H10&
'Private Const SERVICE_WIN32_SHARE_PROCESS = &H20&
'Private Const SERVICE_WIN32 = SERVICE_WIN32_OWN_PROCESS + _
SERVICE_WIN32_SHARE_PROCESS
'Private Const SERVICE_ACCEPT_STOP = &H1
'Private Const SERVICE_ACCEPT_PAUSE_CONTINUE = &H2
'Private Const SERVICE_ACCEPT_SHUTDOWN = &H4
Private Const SC_MANAGER_CONNECT = &H1&
Private Const SC_MANAGER_CREATE_SERVICE = &H2&
'Private Const SC_MANAGER_ENUMERATE_SERVICE = &H4
'Private Const SC_MANAGER_LOCK = &H8
'Private Const SC_MANAGER_QUERY_LOCK_STATUS = &H10
'Private Const SC_MANAGER_MODIFY_BOOT_CONFIG = &H20
Private Const STANDARD_RIGHTS_REQUIRED = &HF0000
Private Const SERVICE_QUERY_CONFIG = &H1&
Private Const SERVICE_CHANGE_CONFIG = &H2&
Private Const SERVICE_QUERY_STATUS = &H4&
Private Const SERVICE_ENUMERATE_DEPENDENTS = &H8&
Private Const SERVICE_START = &H10&
Private Const SERVICE_STOP = &H20&
Private Const SERVICE_PAUSE_CONTINUE = &H40&
Private Const SERVICE_INTERROGATE = &H80&
Private Const SERVICE_USER_DEFINED_CONTROL = &H100&
Private Const SERVICE_ALL_ACCESS = (STANDARD_RIGHTS_REQUIRED Or _
SERVICE_QUERY_CONFIG Or _
SERVICE_CHANGE_CONFIG Or _
SERVICE_QUERY_STATUS Or _
SERVICE_ENUMERATE_DEPENDENTS Or _
SERVICE_START Or _
SERVICE_STOP Or _
SERVICE_PAUSE_CONTINUE Or _
SERVICE_INTERROGATE Or _
SERVICE_USER_DEFINED_CONTROL)
'Private Const SERVICE_AUTO_START As Long = 2
Private Const SERVICE_DEMAND_START As Long = 3
Private Const SERVICE_ERROR_NORMAL As Long = 1
Private Const ERROR_INSUFFICIENT_BUFFER = 122&
Private Enum SERVICE_CONTROL
SERVICE_CONTROL_STOP = 1&
SERVICE_CONTROL_PAUSE = 2&
SERVICE_CONTROL_CONTINUE = 3&
SERVICE_CONTROL_INTERROGATE = 4&
SERVICE_CONTROL_SHUTDOWN = 5&
End Enum
Public Enum SERVICE_STATE
UNINSTALLED = &H0
STOPPED = &H1
START_PENDING = &H2
STOP_PENDING = &H3
RUNNING = &H4
CONTINUE_PENDING = &H5
PAUSE_PENDING = &H6
PAUSED = &H7
End Enum
Private Type SERVICE_STATUS
dwServiceType As Long
dwCurrentState As Long
dwControlsAccepted As Long
dwWin32ExitCode As Long
dwServiceSpecificExitCode As Long
dwCheckPoint As Long
dwWaitHint As Long
End Type
Public Type QUERY_SERVICE_CONFIG
dwServiceType As Long
dwStartType As Long
dwErrorControl As Long
lpBinaryPathName As Long
lpLoadOrderGroup As Long
dwTagId As Long
lpDependencies As Long
lpServiceStartName As Long
lpDisplayName As Long
End Type
Private Declare Function OpenSCManager _
Lib "advapi32" Alias "OpenSCManagerA" _
(ByVal lpMachineName As String, ByVal lpDatabaseName As String, _
ByVal dwDesiredAccess As Long) As Long
Private Declare Function CreateService _
Lib "advapi32" Alias "CreateServiceA" _
(ByVal hSCManager As Long, ByVal lpServiceName As String, _
ByVal lpDisplayName As String, ByVal dwDesiredAccess As Long, _
ByVal dwServiceType As Long, ByVal dwStartType As Long, _
ByVal dwErrorControl As Long, ByVal lpBinaryPathName As String, _
ByVal lpLoadOrderGroup As String, ByVal lpdwTagId As String, _
ByVal lpDependencies As String, ByVal lp As String, _
ByVal lpPassword As String) As Long
Private Declare Function DeleteService _
Lib "advapi32" (ByVal hService As Long) As Long
Private Declare Function CloseServiceHandle _
Lib "advapi32" (ByVal hSCObject As Long) As Long
Private Declare Function OpenService _
Lib "advapi32" Alias "OpenServiceA" _
(ByVal hSCManager As Long, ByVal lpServiceName As String, _
ByVal dwDesiredAccess As Long) As Long '** Change SERVICE_NAME as needed
Private Declare Function QueryServiceConfig Lib "advapi32" _
Alias "QueryServiceConfigA" (ByVal hService As Long, _
lpServiceConfig As QUERY_SERVICE_CONFIG, _
ByVal cbBufSize As Long, pcbBytesNeeded As Long) As Long
Private Declare Function QueryServiceStatus Lib "advapi32" _
(ByVal hService As Long, lpServiceStatus As SERVICE_STATUS) As Long
Private Declare Function ControlService Lib "advapi32" _
(ByVal hService As Long, ByVal dwControl As SERVICE_CONTROL, _
lpServiceStatus As SERVICE_STATUS) As Long
Private Declare Function StartService Lib "advapi32" _
Alias "StartServiceA" (ByVal hService As Long, _
ByVal dwNumServiceArgs As Long, ByVal lpServiceArgVectors As Long) As Long
Private Declare Function NetWkstaUserGetInfo Lib "Netapi32" (ByVal Reserved As Any, ByVal Level As Long, lpBuffer As Any) As Long
Private Declare Function NetApiBufferFree Lib "Netapi32" (ByVal lpBuffer As Long) As Long
Private Declare Function lstrcpy Lib "kernel32" Alias "lstrcpyA" (ByVal lpString1 As Any, ByVal lpString2 As Any) As Long
Private Declare Function lstrlen Lib "kernel32" Alias "lstrlenA" (ByVal lpString As Any) As Long
Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (Destination As Any, Source As Any, ByVal Length As Long)
Private Declare Function lstrlenW Lib "kernel32" (ByVal lpString As Long) As Long
Private Enum InfoLevel
SERVICE_CONFIG_DESCRIPTION = 1
SERVICE_CONFIG_FAILURE_ACTIONS = 2
End Enum
Private Declare Function ChangeServiceConfig2 Lib "advapi32.dll" Alias "ChangeServiceConfig2W" (ByVal hService As Long, ByVal dwInfoLevel As InfoLevel, lpInfo As Any) As Boolean
Private Type SERVICE_DESCRIPTIONW
lpDescription As String
End Type
' This function installs service on local computer
' It returns nonzero value on error
Public Function CreateNTService(Title As String, Nick As String, Link As String, Description As String) As Long
Dim lp As SERVICE_DESCRIPTIONW
lp.lpDescription = Description
Dim hSCManager As Long
Dim hService As Long, DomainName As String
Dim CSC As Long
hSCManager = OpenSCManager(vbNullString, vbNullString, _
SC_MANAGER_CREATE_SERVICE)
If hSCManager <> 0 Then
' Install service to manual start. To set service to autostart
' replace SERVICE_DEMAND_START to SERVICE_AUTO_START
hService = CreateService(hSCManager, Nick, _
Title, SERVICE_ALL_ACCESS, _
SERVICE_WIN32_OWN_PROCESS, _
SERVICE_DEMAND_START, SERVICE_ERROR_NORMAL, _
Link, vbNullString, _
vbNullString, vbNullString, "LocalSystem", _
"")
CSC = ChangeServiceConfig2(hService, 1, lp)
If hService <> 0 Then
CloseServiceHandle hService
Else
CreateNTService = Err.LastDllError
End If
CloseServiceHandle hSCManager
Else
CreateNTService = Err.LastDllError
End If
End Function
Form:
Private Sub Form_Load()
CreateNTService "a", "a", "d:\link", "description"
End
End Sub
The problem is that this code is able to create some description but the description created is "敤捳楲瑰潩n" not "description"
敤 is U+6564. That's clear enough: "d" is ASCII 100 (64 hex) and "3" is 101 (65 hex). I.e. you have a string marshalling problem, in particular with character widths. You will want to call "CreateServiceW", not "*A".
[edit]
Sorry, overlooked where "description" was actually used. Should have been ChangeServiceConfig2A
The problem that I see is that whilst you are correctly using a Unicode version of ChangeServiceConfig2, you are declaring the UDT with a String member. Unfortunately, when VB sees a String type, it automatically converts it from Unicode to the local code page. This messes up your description. The work around is to declare the structuion with a Long member, and then set this value to that of the string's pointer, e.g.
Option Explicit
Private Const STANDARD_RIGHTS_REQUIRED = &HF0000
Private Const SERVICE_WIN32_OWN_PROCESS = &H10&
Private Const SERVICE_QUERY_CONFIG = &H1&
Private Const SERVICE_CHANGE_CONFIG = &H2&
Private Const SERVICE_QUERY_STATUS = &H4&
Private Const SERVICE_ENUMERATE_DEPENDENTS = &H8&
Private Const SERVICE_START = &H10&
Private Const SERVICE_STOP = &H20&
Private Const SERVICE_PAUSE_CONTINUE = &H40&
Private Const SERVICE_INTERROGATE = &H80&
Private Const SERVICE_USER_DEFINED_CONTROL = &H100&
Private Const SERVICE_ALL_ACCESS = (STANDARD_RIGHTS_REQUIRED Or _
SERVICE_QUERY_CONFIG Or _
SERVICE_CHANGE_CONFIG Or _
SERVICE_QUERY_STATUS Or _
SERVICE_ENUMERATE_DEPENDENTS Or _
SERVICE_START Or _
SERVICE_STOP Or _
SERVICE_PAUSE_CONTINUE Or _
SERVICE_INTERROGATE Or _
SERVICE_USER_DEFINED_CONTROL)
Private Const SERVICE_DEMAND_START As Long = 3
Private Const SERVICE_ERROR_NORMAL As Long = 1
Private Const SC_MANAGER_CREATE_SERVICE = &H2&
Private Declare Function OpenSCManager _
Lib "advapi32" Alias "OpenSCManagerA" _
(ByVal lpMachineName As String, ByVal lpDatabaseName As String, _
ByVal dwDesiredAccess As Long) As Long
Private Declare Function CreateService _
Lib "advapi32" Alias "CreateServiceA" _
(ByVal hSCManager As Long, ByVal lpServiceName As String, _
ByVal lpDisplayName As String, ByVal dwDesiredAccess As Long, _
ByVal dwServiceType As Long, ByVal dwStartType As Long, _
ByVal dwErrorControl As Long, ByVal lpBinaryPathName As String, _
ByVal lpLoadOrderGroup As String, ByVal lpdwTagId As String, _
ByVal lpDependencies As String, ByVal lp As String, _
ByVal lpPassword As String) As Long
Private Declare Function CloseServiceHandle _
Lib "advapi32" (ByVal hSCObject As Long) As Long
Private Enum InfoLevel
SERVICE_CONFIG_DESCRIPTION = 1
SERVICE_CONFIG_FAILURE_ACTIONS = 2
End Enum
Private Declare Function ChangeServiceConfig2 Lib "advapi32.dll" Alias "ChangeServiceConfig2W" (ByVal hService As Long, ByVal dwInfoLevel As InfoLevel, ByRef lpInfo As SERVICE_DESCRIPTIONW) As Boolean
Private Type SERVICE_DESCRIPTIONW
lpDescription As Long
End Type
' This function installs service on local computer
' It returns nonzero value on error
Public Function CreateNTService(ByRef Title As String, ByRef ServiceName As String, ByRef BinaryPath As String, ByRef Description As String) As Long
Dim hSCManager As Long
Dim hService As Long
Dim DomainName As String
Dim CSC As Long
Dim lp As SERVICE_DESCRIPTIONW
hSCManager = OpenSCManager(vbNullString, vbNullString, _
SC_MANAGER_CREATE_SERVICE)
If hSCManager <> 0 Then
' Install service to manual start. To set service to autostart
' replace SERVICE_DEMAND_START to SERVICE_AUTO_START
hService = CreateService(hSCManager, ServiceName, _
Title, SERVICE_ALL_ACCESS, _
SERVICE_WIN32_OWN_PROCESS, _
SERVICE_DEMAND_START, SERVICE_ERROR_NORMAL, _
BinaryPath, vbNullString, _
vbNullString, vbNullString, "LocalSystem", _
"")
lp.lpDescription = StrPtr(Description) ' Set the string pointer.
CSC = ChangeServiceConfig2(hService, 1, lp)
If hService <> 0 Then
CloseServiceHandle hService
Else
CreateNTService = Err.LastDllError
End If
CloseServiceHandle hSCManager
Else
CreateNTService = Err.LastDllError
End If
End Function
Related
I Have a series of tests that need to pass one of them includes deleting the buffer between the defined region (which is between the marker and cursor) and inserting the cut text in the paste. I then need to set the cursor and marker to the beginning of the cut text (see below code for a better understanding)
class Buffer(s: String) {
import scala.collection.mutable.StringBuilder
import scala.io.StdIn
private var buffer: StringBuilder = new StringBuilder(s)
private var cursor: Int = 0 // cursor is in between characters
private var marker: Int = 0 // marker is in between characters
private var paste: String = ""
private def end: Int = buffer.length // the end of the line
private def lwr: Int = Math.min(marker, cursor)
private def upr: Int = Math.max(marker, cursor)
/*
* Accessor methods to return aspects of the state
*/
def getCursor: Int = cursor
def getMarker: Int = marker
def getString: String = buffer.toString
def getPaste: String = paste
Delete the contents of the defined region and save the cut string in the paste
buffer. This operation re-sets the cursor and the marker to the start of the
cut text. For example:
B U F F E R marker = 1
^ ^ cursor = 4
Then perform xd()
B E R marker = 1
^ cursor = 1
*/
I have written some code:
def xd() {
paste = buffer.substring(lwr, upr)
buffer = buffer.delete(lwr, upr)
cursor = end
marker = end
}
this seems to pass the other tests but does not set the marker and cursor.
Any suggestions please?
First in Scala you would try to have no mutable state (var).
Here is a solution for cut and paste that is immutable:
case class Buffer(s: String, paste: String, private val cursor: Int = 0, private val marker: Int = 0) {
def mark(str: String): Buffer = {
val startIndex = s.indexOf(str)
val endIndex = startIndex + str.length
Buffer(s, startIndex, endIndex)
}
def cut(): Buffer = {
Buffer(s.take(cursor) + s.drop(marker), // rest of the String
s.take(marker).drop(cursor)) // paste of the String
}
}
You can use it like this:
Buffer("hello there") // > Buffer(hello there,,0,0)
.mark("o t") // > Buffer(hello there,,4,7)
.cut() // > Buffer(hellhere,o t,0,0)
You see the result of each line.
Let me know if you need more support or if I misunderstood you.
I am fairly new to scala , play framework and argonaut.
Following is my case class which contains a variable of type List[Remedy]
My aim is to generate a json response of the PredictionModel object which contains JsonArray of List[Remedy].
package models
import scala.collection.mutable.ListBuffer
import argonaut._, Argonaut._
/**
* Created by abhishek on 15/01/16.
*/
case class PredictionModel() {
var aboutKundali: AboutKundli = new AboutKundli()
var planetStatus = new ListBuffer[PlanetStatus].toList
var donate = ""
var notToDonate = ""
var colorNotToWear = ""
var favouredGod = ""
var aboutEducationAndOccupation = ""
var mixMahaDashaCurrent = ""
var mixMahaDashaNotCurrent = ""
var category = ""
var rinnPitri = ""
var lifeHead = ""
var disease = ""
var occupation = ""
var marriedLife = ""
var santan = ""
var parents = ""
var nature = ""
var remedyList = new ListBuffer[Remedy].toList
var importantInformation = ""
}
Implicit for PredictionModel is written like :-
implicit def predicationEncodeJson: EncodeJson[PredictionModel] =
EncodeJson((prediction: PredictionModel) =>
("about_kundali" := argonaut.Json(
"birth_rashi" := prediction.aboutKundali.birthRashi,
"lagan_rashi" := prediction.aboutKundali.laganRashi,
"birth_day_planet" := prediction.aboutKundali.birthDayPlanet,
"birth_time_planet" := prediction.aboutKundali.birthTimePlanet,
"current_maha_dasha" := prediction.aboutKundali.currentMahaDasha,
"lucky_day" := prediction.aboutKundali.luckyDay,
"lucky_number" := prediction.aboutKundali.luckyNumber
)) ->:
("important_information" := prediction.importantInformation) ->:
("rinnPitri" := prediction.rinnPitri) ->:
("category" := prediction.category) ->:
("mix_mahadasha_not_current" := prediction.mixMahaDashaNotCurrent) ->:
("mix_mahadasha_current" := prediction.mixMahaDashaCurrent) ->:
("about_education_and_occupation" := prediction.aboutEducationAndOccupation) ->:
("favored_god" := prediction.favouredGod) ->:
("color_not_to_wear" := prediction.colorNotToWear) ->:
("donate" := prediction.donate) ->:
("not_to_donate" := prediction.notToDonate) ->: jEmptyObject)
Everything about runs just fine, but what should i do to add JsonArray in prodiction Json object
Edit 1
As suggested here is my test case class
import argonaut._, Argonaut._
case class TestModel(id: Int, name: String) {
}
object TestModel{
implicit def PredictionModelCodecJson = CodecJson[TestModel] =
casecodec20(TestModel.apply, TestModel.unapply)("id", "name")
}
While declaring casecodec20 i have an error in apply and unapply method.
Do i need to over-ride them ?
Also how to call this implicit value ?
Edit 2
So here is what needs to be done.
Create case class with all the parameters in constrcutor and a subsequent object class which contains CodecJson like below
case class Remedy(no: Int, description: String) {
}
object Remedy{
implicit def RemedyCodecJson: CodecJson[Remedy] =
casecodec2(Remedy.apply, Remedy.unapply)("number", "description")
}
In my case i had more complex models inside models so i just created implicit CodecJson for all.
How to use it ?
remedy.asJson
When you have a case class it is much easier because you can use casecodec:
implicit def PredictionModel CodecJson: CodecJson[PredictionModel] =
casecodec20(PredictionModel.apply, PredictionModel.unapply)("aboutKundali", "planetStatus", "donate", .....)
And now you have a JSON codec for your PredictionModel which will encode and decode your case class from/to json.
In order to make it work you can define your AboutKundli, PlanetStatus and Remedy as case classes and create casecodecs for them in a similar way.
Note that it is highly recommended to declare case classes in a way where all the paramerers are defined in their constructors and not how you show in your example. A better way would be:
case class PredictionModel(
aboutKundali: AboutKundli,
planetStatus: List[PlanetStatus],
donate: String,
notToDonate: String
colorNotToWear: String
favouredGod: String,
aboutEducationAndOccupation: String,
mixMahaDashaCurrent: String,
mixMahaDashaNotCurrent: String,
category: String,
rinnPitri: String,
lifeHead: String,
disease: String,
occupation: String,
marriedLife: String,
santan: String,
parents: String,
nature: String,
remedyList: List[Remedy],
importantInformation: String)
It is not only stylistic and there are technical reasons to do so (related to how apply/unapply/equality are generated for the case class) so it is better to follow this practice.
In general you should follow the rule that case classes are immutable and all the values are declared as their constructor parameters.
Once you have declared codecs for your case classes you have codecs for lists "for free" because Argonaut can encode List[A] if it can see that it can encode that A, so you don't need to do anything special here.
I'd like a container class that I can extend with some number of traits to contain groups of default vals that can later be changed in an immutable way. The traits will hold certain simple pieces of data that go together so that creating the class with a couple of traits will create an object with several collections of default values.
Then I'd like to be able to modify any of the vals immutably by copying the object while changing one new value at a time.
The class might have something like the following:
class Defaults(val string: String = "string", val int: Int = "int")
Then other traits like this
trait MoreDefaults{
val long: Long = 1l
}
Then I'd like to mix them when instantiated to build my the particular needed set of defaults
var d = new Defaults with MoreDefaults
and later to something like:
if (someFlag) d = d.copy( long = 1412341234l )
You can do something like this with a single case class but I run out of params at 22. But I'll have a bunch of groupings of defaults I'd like to mixin depending on the need, then allow changes to any of them (class defined or trait defined) in an immutable way.
I can stick a copy method in the Defaults class like this:
def copy(
string: String = string,
int: Int = int): Defaults = {
new Defaults(string, int)
}
then do something like
var d = new Defaults
if (someFlag) d = d.copy(int = 234234)
Question ====> This works for values in the base class but I can't figure how to extend this to the mixin traits. Ideally the d.copy would work on all vals defined by all of the class + traits. Overloading is trouble too since the vals are mainly Strings but all of the val names will be unique in any mix of class and traits or it is an error.
Using only classes I can get some of this functionality by having a base Defaults class then extending it with another class that has it's own non-overloaded copyMoreDefault function. This is really ugly and I hope a Scala expert will see it and have a good laugh before setting me straight--it does work though.
class Defaults(
val string: String = "one",
val boolean: Boolean = true,
val int: Int = 1,
val double: Double = 1.0d,
val long: Long = 1l) {
def copy(
string: String = string,
boolean: Boolean = boolean,
int: Int = int,
double: Double = double,
long: Long = long): Defaults = {
new Defaults(string, boolean, int, double, long)
}
}
class MoreDefaults(
string: String = "one",
boolean: Boolean = true,
int: Int = 1,
double: Double = 1.0d,
long: Long = 1l,
val string2: String = "string2") extends Defaults (
string,
boolean,
int,
double,
long) {
def copyMoreDefaults(
string: String = string,
boolean: Boolean = boolean,
int: Int = int,
double: Double = double,
long: Long = long,
string2: String = string2): MoreDefaults = {
new MoreDefaults(string, boolean, int, double, long, string2)
}
}
Then the following works:
var d = new MoreDefualts
if (someFlag) d = d.copyMoreDefaults(string2 = "new string2")
This method will be a mess if Defaults get's changed parameters! All the derived classes will have to be updated--ugh. There must be a better way.
I don't think I'm strictly speaking answering your question, rather suggesting an alternative solution. So your having problems with large case classes, e.g.
case class Fred(a: Int = 1, b: Int = 2, ... too many params ... )
What I would do is organize the params into more case classes:
case class Bar(a: Int = 1, b: Int = 2)
case class Foo(c: Int = 99, d: Int = 200)
// etc
case class Fred(bar: Bar = Bar(), foo: Foo = Foo(), ... etc)
Then when you want to do a copy and change, say one of the values of Foo you do:
val myFred: Fred = Fred()
val fredCopy: Fred = myFred.copy(foo = myFred.foo.copy(d = 300))
and you need not even define the copy functions, you get them for free.
I have:
class XCClass
{
#native protected def createWin(displayPtr: Long, width: Int, height: Int, backGroundColour: Int = white.value,
borderColour: Int = darkblue.value, borderWidth: Int = 0, xPosn: Int = 0, yPosn: Int = 0): Long
#native protected def xOpen(): Long
System.load("/sdat/projects/prXCpp/Release/libprXCpp.so")
//Code edited out
class Window(width: Int, height: Int, backGroundColour: ColourInt = white, borderColour: ColourInt = darkblue,
borderWidth: Int = 0, xPosn: Int = 0, yPosn: Int = 0)
{
val xWinPtr = createWin(xServPtr, width, height, backGroundColour.value, borderColour.value, borderWidth, xPosn, yPosn)
#native def drawLine(x1: Int, y1: Int, x2: Int, y2: Int): Unit
}
}
The first two methods work fine, but the native method on the inner class gives
object XApp extends App
{
val xc:XCClass = XCClass()
val win: xc.Window = xc.Window(800, 600)
win.drawLine(20, 20, 40, 40)
readLine()
}
Exception in thread "main" java.lang.UnsatisfiedLinkError: pXClient.XCClass$Window.drawLine(IIII)V
Here's the C++ signature
extern "C" JNIEXPORT void JNICALL Java_pXClient_XCClass$Window_drawLine(JNIEnv * env, jobject c1, Display *dpy,
Window win, jint x1, jint y1, jint x2, jint y2)
I tried using an underscore instead of the $ sign, and having no inner name at all but that failed as well.
Edit2: I managed to get javah to work just before seeing Robin's answer and it gave
JNIEXPORT void JNICALL Java_pXClient_XCClass_00024Window_drawLine
(JNIEnv *, jobject, jint, jint, jint, jint);
Edit4: It worked fine once I'd corrected errors in my code. It seems that the JVM will import a native function with the wrong parameter signature as long as the name is correct.
I just did a quick test with a .java file and javah, and a $ is represented as _00024.
I seem to have some trouble overloading opIndexAssign in one of my classes.
I have a class; JSObject which is defined like this:
alias char[] String;
...
class JSObject : Dobject
{
/*****************************************************************
* Constructors
******************************************************************/
this( Dobject dobj )
{
super( dobj ) ;
}
this()
{
super( null ) ;
}
this( AssociativeArray data )
{
// initiate
super( null ) ;
// then populate
foreach( k, v ; data )
{
this[ k ] = v ;
}
}
public void opIndexAssign( String key , String val )
{
Value* v = new Value() ;
v.putVstring( val ) ;
this.Put(key, v , DontDelete);
}
public void opIndexAssign( String key , Dobject dobj )
{
Value* v = new Value() ;
v.putVobject( dobj ) ;
this.Put(key, v , DontDelete);
}
public void opIndexAssign( String key , JSObject jso )
{
Value* v = new Value() ;
v.putVobject( jso ) ;
this.Put(key, v , DontDelete);
}
public Value* opIndex( String key )
{
return this.Get( key );
}
}
The Dobject superclass has overloaded put() and get() methods and I'm trying to wrap them so I can access them as associative arrays:
77: JSObject jso = new JSObject() ;
78: jso[ "foo" ] = "bar" ;
79:
80: JSObject jsoParent = new JSObject() ;
81: jsoParent[ "child" ] = jso ;
It works for the String,String method but when I try using the JSObject as the value, it fails.
test2.d => test2
+ c:\dmd\dsss\bin\rebuild.exe -version=PhobosCompatibility -w -Idsss_imports\ -I. -S.\ -Ic:\dmd\dsss\include\d -Sc:\dmd\dsss\lib\ -Ic:\dmd\dsss\include\d -Sc:\dmd\dsss\lib -oqdsss_objs\D -debug -gc test2.d -oftest2
test2.d(81): Error: function dmdscripttest.JSObject.opIndexAssign (char[],char[]) does not match parameter types (JSObject,char[5u])
test2.d(81): Error: cannot implicitly convert expression (jso) of type dmdscripttest.JSObject to char[]
test2.d(81): Error: cannot implicitly convert expression ("child") of type char[5u] to dmdscripttest.JSObject
Error: Command failed, aborting.
Command c:\dmd\dsss\bin\rebuild.exe returned with code 1, aborting.
I'm a bit at loss to what I'm doing wrong. It's like the compiler tries to cast it to fit with opIndexAssign( String, String ) instead of the opIndexAssign( String, JSObject ) method.
Did I define the opIndexAssign functions incorrectly?
Thanks in advance,
the issue is that opIndexAssigne needs the value first and then the keys (or indices)
http://www.d-programming-language.org/operatoroverloading.html#Assignment
so you'll want to define it as
public void opIndexAssign( String val , String key)
{
Value* v = new Value() ;
v.putVstring( val ) ;
this.Put(key, v , DontDelete);
}
public void opIndexAssign( Dobject dobj , String key)
{
Value* v = new Value() ;
v.putVobject( dobj ) ;
this.Put(key, v , DontDelete);
}
public void opIndexAssign( JSObject jso , String key)
{
Value* v = new Value() ;
v.putVobject( jso ) ;
this.Put(key, v , DontDelete);
}
the reason this is done is so that you can define a vararg for the index