Clipboard

Monkey Targets Forums/Desktop/Clipboard

sereschkin(Posted 2014) [#1]
Hello there,

I am trying to implement a copy paste function for my glfw application. This is where I stuck:

I've created a cpp-file with following content
class Clipboard
{
	public:
	
	static void SetClipboard(char* string)
	{
		glfwSetClipboardString(window, string);
	}
	
	static char* GetClipboard()
	{
		glfwGetClipboardString(window);
	}
	
	static GLFWwindow *window;
};

GLFWwindow *Clipboard::window=BBGlfwGame::GlfwGame()->GetGLFWwindow();


I can compile it, but an error message gets thrown:

TRANS Failed: Error executing './MonkeyGame', return code=11.


What am I missing? Btw: My c++ skills are next to zero.


ziggy(Posted 2014) [#2]
Not sure a Monkey string is a char*


sereschkin(Posted 2014) [#3]
Well, at least this is what I found on documentation for using the clipboard functions. :(

The monkey file looks like:
Import "native/clipboard.${TARGET}.${LANG}"

#If TARGET="glfw"
Extern
	Function GetClipboard:String() = "Clipboard::GetClipboard"
Public
#EndIf


After modifying the cpp file it looks now like:

class Clipboard
{
	public:

	static String GetClipboard()
	{
		const char* buf = glfwGetClipboardString(window);
		
		int max = 4096;
		size_t len = 0;
	    while( (len < max) && (buf[ len ] != '\0') ) {
	        len++;
	    }
	    
		return String( buf, len );
	}
	
	static GLFWwindow *window;

};

GLFWwindow *Clipboard::window=BBGlfwGame::GlfwGame()->GetGLFWwindow();


But still the same error :( Do I have to reference somehow to BBGlfwGame?


DruggedBunny(Posted 2014) [#4]
You might need to do some wrapping to get C strings to work:

/Community/posts.php?topic=8652&post=90329

Download the zip file from there and take a look at hardwiredlib.cpp and hardwired.monkey to see how the C++ and Monkey files exchange string data. You might also want to read the previous page in that thread for some explanations...


DruggedBunny(Posted 2014) [#5]
You might need to do some wrapping to get C strings to work:

http://www.monkey-x.com/Community/posts.php?topic=8652&post=90329

Download the zip file from there and take a look at hardwiredlib.cpp and hardwired.monkey to see how the C++ and Monkey files exchange string data. You might also want to read the previous page in that thread for some explanations...


sereschkin(Posted 2014) [#6]
Thank you DruggedBunny. I will take a look and report asap.


sereschkin(Posted 2014) [#7]
Thanks to your input I could make the clipboard functions for glfw3 work:

Monkey file (clipboard.monkey):
Import "native/clipboard.${TARGET}.${LANG}"

#If TARGET="glfw"
Extern
	Function GetClipboard:String() = "Clipboard::GetClipboard"
	Function SetClipboard:Void(value:String) = "Clipboard::SetClipboard"
Public
#EndIf


And c++ file (clipboard.glfw.cpp):
class Clipboard
{
	public:
	
	static void SetClipboard(String value)
	{
		const Char* Source = value.Data();
		char* Dest = new char[value.Length()+1]();
		
		int i = 0;

		while(Source[i] != '\0' && i < value.Length()-1)
		{
			Dest[i] = (char)Source[i];
			++i;
		}
		
		Dest[value.Length()]= '\0';
	    
		glfwSetClipboardString(BBGlfwGame::GlfwGame()->GetGLFWwindow(), Dest);
	}
	
	static String GetClipboard()
	{
		const char* buf = glfwGetClipboardString(BBGlfwGame::GlfwGame()->GetGLFWwindow());
		size_t len = 0;
		
		while((buf[len] != '\0')) 
		{
			len++;
		}
		
		return String( buf, len );
	}
};


Maybe this is useful for one.


ImmutableOctet(SKNG)(Posted 2014) [#8]
@sereschkin: You really shouldn't be using that code you posted. First of all, 'ToCString' is your friend. Mark made it as nice as it is for a reason; I learned this the hard way. Second of all, that's a pretty bad memory leak, you're not even deleting what you create. I decided to give in, and just add this to my 'util' module. Here's the current version of the GLFW external code for it (Currently just clipboard functionality). That shouldn't have a memory leak like what you posted, and it should be a lot faster, not to mention more efficient. I should also mention that my code uses 'strlen', which you should use as well.

Obviously, this code is based on GLFW3.


sereschkin(Posted 2014) [#9]
Your solution is so easy O_o. Thank you. I have seen this toCString Method but could'nt get it to work. I encountered error messages like "Bus Error" and 2 other messages. Also I thought that everything is memory managed in monkey, but now it makes sense to me that extern native code is of course not, at least in case of unmanaged languages. Is srtlen a "standard" c++ command? And yes, this code is based on glfw3. I also need mouse wheel functionality. There is a solution in the forums for last version of glfw but not for the current, and as my c++ knowledge just isn't there it is very frustrating, but that is another topic.

EDIT: Tried out your solution and GetClipboard works as expected, but SetClipboard doesn't do anything for me :(.

EDIT2: For me the following works as expected:

	static void SetClipboard(String value)
	{
		glfwSetClipboardString(BBGlfwGame::GlfwGame()->GetGLFWwindow(), value.ToUtf8());
	}




ImmutableOctet(SKNG)(Posted 2014) [#10]
I'm not too sure on the mouse wheel front. But the 'strlen' command is part of the C standard library. Implementations of the C standard library are obviously available from most (If not all) C++ compilers. The C++ standard library tends to be less memory and hardware oriented (At least in terms of direct interfaces; but you get the idea). Since we were using raw character arrays, C (And by extension, C++) supplied the correct utilities. The 'strlen' command is mainly for 'NULL' terminated strings, and that was what we were dealing with here.

I have no idea why you had problems with this, but here's hoping it's nothing on Monkey's side.

Anyway, on to the main point of this comment:

The 'String' and 'Array' types Monkey supplies are stack-based containers for (From what I remember, heap allocated) data. They will pretty much handle references and destruction automatically, even with native code. Something like the data behind a character-pointer (char*), on the other hand, will not be garbage collected. That's getting into C++ territory. Monkey's 'ToCString' command is actually really nicely made, it will deal with the garbage (If any) for you. The 'ToCString' command used to have a memory leak, but ever since Mark fixed it, it's worked really well. Back when I first tried messing with 'Strings' natively, I had to use 'Data' and other methods of getting the internal data.

Standard pointers can be used with Monkey's objects, you just need to call their Monkey-based constructor(s) instead of the usual C++ style. But as far as passing around pointers to Monkey-based types goes, it's effectively the same as usual OO in C++. If you're curious about how things get generated, write some basic programs and then compile them with the STDCPP (C++ Tool) target. From there, just look at the contents of 'bbMain' (And the generated functions around it).

Here's a simple example I made:


Here's the generated code (Cleaned up a bit, so it's actually readable):


Needless to say, Monkey does some weird things with "For-Each" loops. But other than that, you can see how objects are handled. Monkey's 'Object' class does most of the hard work here (With regard to garbage collection). I'm not sure why Mark doesn't have it use the '+=' operator with this builder, but it's not a big deal. Also keep in mind that I manually reformatted that to make it actually readable. Monkey's compiler is both good and bad because of this; it uses as few characters as possible, but the code looks awful.

I hope this helps you with understanding what Monkey does when compiling. I'd recommend poking around in your own generated source at some point. Obviously, generated code is different for each target, but most things should be the same between C and C++ targets.


ImmutableOctet(SKNG)(Posted 2014) [#11]
Wait, you were having problems with my version of 'setClipboard'? It works fine for me, but I should probably use 'ToUtf8', it has a small bit of extra code regarding formatting. I don't see how that'd break much, though. Either way, I'll update my version on github in a minute.


sereschkin(Posted 2014) [#12]
Thank you for such a detailed explanation. I forgot to mention that I'm on a mac here. And documentation for glfwSetClipboardString (documentation on glfw.org) says also that it has to be an utf8 formatted const char. Haven't seen this before.


ImmutableOctet(SKNG)(Posted 2014) [#13]
Yeah, I'm on Windows, so that probably has something to do with not spotting it earlier. All I had to do in order to test this was copy some Japanese characters (Kanji and Kana in this case), and sure enough, it broke. Using 'ToUtf8' fixed it, so I should be good, thanks.

Also, the forums don't use markdown, so you'll have to use "BBCode" (Or whatever they call it), there should be a "forum codes" thing on the bottom right about that. You'll want 'a' for links.

Never mind, you found the forum codes.


sereschkin(Posted 2014) [#14]
Yep, just found the forum codes link :D. Thanks